I have an app that relies on several managed libraries. These managed libraries in turn rely on some unmanaged libraries.
When I deploy the app to a machine running XP, it runs fine. When I do the same on a machine running Vista, I get a DLL not found exception.
I've tried both a VS2010 setup project and an NSIS installer to do the deployment and it's the same in both cases.
Why might this happen? What can I do to get around it?
Update - Further details
- Both installers check for the installation of .NET 4.0 and install it if need be
- The Vista computer is 64 bit, but the installation gets directed to the x86 program files folder as expected
- In both cases I have an admin account
- The DLLs are kept in the same directory as the executable
- As far as I can tell, the files are getting copied to the right directory
Update 2
- The full error is at http://pastebin.ca/2046487
- The DLL is Audiere.Net.dll, which is one of mine and is a managed library.
I'm not sure if that error means that it can't find Audiere.Net.dll, or whether it can't load it because one of it's dependencies can't be found.
Update 3 - Stuff from Process Monitor
After running process monitor (thanks Mehrdad!) there are several entries which don't have a status of "SUCCESS". Some of these are "NAME NOT FOUND" and some are "PATH NOT FOUND". (It's even querying the PDB files, which I had thought were only used by a debugger.) It's really hard to see which entries might be the one leading to the actual failure. Anyway, I've uploaded the log (filtered to have a relevant path) in case it means something to anyone.
Update 4 - Added .pdb files
So I kinda got desperate and included the .pdb files to the output of the installer. I thought it would be useless, but it actually resulted in a more useful error. Rather than simply saying DLL not found, I now get a BadImageFormatException. Googling this tells me that this is a common problem for binaries compiled on x86 but being run on x64 (as the Vista machine is).
The suggested remedy is to force it to target x86, but Audiere.Net.dll already was. Could the fault lie with the library that it wraps?
Maybe there's some sort of redirection that's not actually letting your app install in the intended folder?
We'd need a bit more detail, but are you installing for the user or the machine? Are you an admin? Where is the DLL normally located?
Edit: Try using Process Monitor to monitor what file is actually being accessed.
If you are running a .Net application, do both computers have the proper Framework installed?
You mention that Audiere.Net.dll is targeted at x86, but what about your executable?
You can obviously recompile your program or use Corflags (part of the framework) to view the current setting on your exe.
Corflags ssd2.exe
Or to set or unset the flag
Corflags ssd2.exe /32BIT+
Corflags ssd2.exe /32BIT-
(Note, if your app is signed with a strong name it won't work unless you use /Force to remove the signature)
The solution turned out to be quite straightforward: one of the unmanaged DLLs needed to be recompiled for x64.
Key steps:
- Check process monitor for likely sources of error. Look carefully at the error report that Windows offers to send when the app crashes.
- Include the .pdb files for managed libraries. This seemed to result in more informative error messages.
- These error messages not only specified which managed library was causing the error, but also indicated that it was a x86/x64 issue. (
BadImageFormatException
)
- Following some sound advice, check that all of the unmanaged libraries are targeting x86. (Mine were, but it's good to be sure.)
- Recompile the unmanaged dependencies of the troublesome managed library on an x64 machine.
- Write an install script that copies the appropriate (x86 or x64) version of the DLL.
- Profit!
Specifics:
- The problem I had seemed to be with
Audiere.Net.dll
, but was actually caused by a problem with libaudieresharpglue.dll
.
- I use NSIS for installers. To accomplish the architecture specific DLL, I used a header called x64.nsh.
Usual reason is that the dll in question depends on other dlls which are not on the Vista machine (or possibly there but not registered.)
We ran into something simlar and found we needed to download the c++ Redistibuatable Package to get the program to run on windows 7 using 3rd party dlls.
I recall running into a similar issue with SQLite wrapper.
The source of the problem is the 32/64 bit issue of course, and it's the same scenario as the SQLite wrapper is a managed wrapper which makes it processor dependent.
I am guessing that while you're managed lib (Audiere.Net.dll) is compiled for 32 bits, you main application (ssd2.exe) is not.
The installation folder is determined by the configuration of the setup, but if the application project is not strictly configured to compile as a x86 project (usually targeting the default Any Cpu environment) then the application will launch as a 64 bit process, regardless of the installation path. This can be easily verified by looking at the process in task manager on a 64 bit machine, all 32 bit processes have an additional *32 on a 64 bit windows machine (they won't have it on a 32 bit machine).
EDIT: or more easily by looking at the project properties->Build-> Platform Target :)
Anyhow - you should change the project settings for the project that builds ssd2.exe to target x86 and you should be ok.