2

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

  1. Both installers check for the installation of .NET 4.0 and install it if need be
  2. The Vista computer is 64 bit, but the installation gets directed to the x86 program files folder as expected
  3. In both cases I have an admin account
  4. The DLLs are kept in the same directory as the executable
  5. As far as I can tell, the files are getting copied to the right directory

Update 2

  1. The full error is at http://pastebin.ca/2046487
  2. 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?

Tom Wright
  • 11,278
  • 15
  • 74
  • 148

7 Answers7

2

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.

user541686
  • 205,094
  • 128
  • 528
  • 886
  • Good questions. I've updated the question to include this information. – Tom Wright Apr 14 '11 at 18:13
  • @Mehrdad - Process Monitor looks like a really useful tool. Thanks for drawing my attention to it. I've uploaded a log if you fancy taking a peek. – Tom Wright Apr 14 '11 at 19:23
  • @Tom: Yes, it's pretty much *the* tool every developer should have. :-) I'll take a look at it, sure. Of course, do be aware that just because something isn't found doesn't mean it's really the problem, so it'll take a little bit of practice to find the right error. – user541686 Apr 15 '11 at 00:10
  • @Tom: Try copying MSVCR100D.dll into your folder (you might need to download the Visual C 2010 Runtime); does it fix the issue? – user541686 Apr 15 '11 at 00:38
  • I had really strong hopes for MSVCR100D.dll (I seem to remember needing to do this for another project), but it didn't help. Any other bright ones @Mehrdad? – Tom Wright Apr 19 '11 at 13:02
  • @Tom: Aw bummer. Not really, can't think of anything right now. :( – user541686 Apr 19 '11 at 14:09
  • Bounty awarded since Process Monitor was the key to me discovering what I needed to do. – Tom Wright Apr 20 '11 at 19:21
1

If you are running a .Net application, do both computers have the proper Framework installed?

Jess
  • 2,991
  • 3
  • 27
  • 40
  • Do you have the "Full" Framework installed? Just the x64 version? I'm just chasing the incompatible libraries. – Jess Apr 14 '11 at 18:16
  • If its not that, do you have any hard-coded [DllImport()] statements in your code? – Jess Apr 14 '11 at 18:18
  • The framework that gets installed is the same on both machines and is (AFAIK) the full version. I don't use any [DllImport()] statements in my code, but I suspect there must be some baked into the wrapper DLLs. I would imagine they're relative though - and they work on XP. – Tom Wright Apr 14 '11 at 19:22
1

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)

sgmoore
  • 15,694
  • 5
  • 43
  • 67
1

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.
Tom Wright
  • 11,278
  • 15
  • 74
  • 148
0

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.)

sgmoore
  • 15,694
  • 5
  • 43
  • 67
  • OK, but how do I find out which DLL is missing? The directory I'm running it from in Vista contains the same files as the directory on XP and in bin/Release on my dev machine. – Tom Wright Apr 19 '11 at 13:01
  • I usually first try Process Explorer (from Sysinternals/Microsoft) on the working machine. It has an option to show (on the lower half of the screen) the dlls that have been loaded by a process. It will obviously show quite a few windows components, but sometimes something stands out, such as a dependency on the Microsoft C runtime library (or VB library). Unfortunately there may be dll's that hook into each process simply because they are on your machine and does not mean that they are needed. (Eg, if I look at Dropbox, one of Apple's Bonjour dlls are loaded, but I don't expect it is needed) – sgmoore Apr 20 '11 at 11:50
  • The second method is to use Process Monitor also from Sysinternals. This allows you to see all the files that the program is loading or attempting to load. It will show you a lot of information, so you need to filter it to just show information from your process and just file access. Again, this is not simple as there are some files that your process will load if there are there, but are not needed. (For example, to localize an application). I usually work backwards, starting at the point where it crashes. Once you find a dll that is missing, you check it is exists on the working machine. – sgmoore Apr 20 '11 at 11:56
  • Looking at the sysinternals log, it is missing or not finding MSVCR100D.dll, so I think this was done before you copied MSVCR100D.dll to your machine. Can you repeat the process as it may be getting a little further, but still missing a file, (maybe even msvcr100.dll) – sgmoore Apr 20 '11 at 12:51
0

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.

Chad
  • 1,512
  • 1
  • 16
  • 40
0

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.

NightDweller
  • 913
  • 5
  • 8
  • Sadly no. This was one of the first thing I tried. The reason I only specified Audiere.Net.dll was that it was the bit that was mentioned in the error. Thanks for the suggestion though. – Tom Wright Apr 19 '11 at 23:36
  • @Tom Wright - mm..did you verify that the process is actually running as a *32 bit process on the 64 bit machine? – NightDweller Apr 19 '11 at 23:43
  • I'm asking because you may have a different build configuration for the setup project (or maybe some script that build the setup..or something of that sort) – NightDweller Apr 19 '11 at 23:50
  • I see. For what it's worth, I've been using NSIS to make the installer. How could I be 100% sure that it's running as a 32 bit app though? – Tom Wright Apr 20 '11 at 10:29
  • 1
    Open Task Manager on the 64 bit machine, and look for the ssd2.exe process. 32 bit processes appear as "ssd2.exe*32" on 64 bit windows. You can also check the InPtr size (if (IntPtr.Size == 4) Console.WriteLine("I am a 32 bit process)"; else Console.WriteLine("I am a 64 bit process"); – NightDweller Apr 20 '11 at 11:09