January 1, 2006
Visual Studio 2005 DLL HellPosted 2700 days ago on January 1, 2006
Microsoft is making strenuous efforts to eliminate DLL Hell. But is the cure worse than the disease? I'm trying to get my head round what has changed in Visual Studio 2005 with regard to unmanaged DLLs and their dependencies. I learned about this the hard way, when compiling the latest version of Sqlite and a Java JNI wrapper for Sqlite. A key factor here is that like many open source and cross-platform libraries, these are most often compiled from the command-line. I tweaked the make files, ran the latest vcvars32.bat, and got an apparently successful build. However, when I attempted to use the wrapper from Java I got an error I hadn't seen before. I have a feeling we may run across this now and again, so take a look at this:
In case you can't see the image, the message is: "The application has failed to start because MSVCR80.dll was not found. Re-installing the application may fix this problem." All a bit strange, because MSVCR80.DLL was most definitely installed; in fact a quick search revealed multiple copies on my system. However, I did the obvious thing and copied one from the Visual C++ redist folder to the application directory. Far from solving the problem, it simply changed the error to this one:
which says, "An application has made an attempt to load the C runtime library incorrectly. Please contact the application's support team for more information." Indeed. So what is going on here?
MSVCR80.DLL is the latest version of Microsoft's C runtime library. Actually there are several runtime libraries, but this is the default for DLLs compiled with the Visual Studio 2005 compiler and linker. Version mismatches in the C runtime library are a common source of application failure, so Microsoft is now enforcing the use of a manifest that identifies the exact version of the dependent file, enabling "side by side" existence of multiple versions without conflict.
That sounds fair enough, but there are many complicating factors. Not all versions of Windows support side-by-side execution, and even on those that do, the installation procedure is complex; it is more than just copying a DLL. This article does a fair job of explaining the deployment issues. However, it still wasn't clear to me why I was getting the error, especially since the compiler had generated a manifest for me. I ran vcredist_x86.exe to no avail.
I found a solution that worked for me in Richard Grimes' detailed article about unmanaged assemblies. Note that he is not polite about how all this stuff has been implemented. In essence, I had to run the mt utility as a post-build step, to embed the generated manifest into the DLL as a resource. It must be resource #2 for this to work. After that, everything was fine, though I haven't yet tried to build an installer that would be suitable for wide deployment.
I did some further tests with my simple Sqlite wrapper for Delphi, and the plain (non-JNI) version of Sqlite3.dll, and got exactly the same error.
If you compile your DLL from the Visual Studio 2005 IDE, rather than from the command-line, you will not notice this issue on your development machine. This is because the IDE will create the manifest and embed it for you. However, you still have a deployment issue. This means using a supplied merge module in a Windows Installer setup, or running vcredist_x86.exe on the target machine. The snag here is that vcredist_x86.exe (and the merge module) have their own dependencies, primarily version 3.0 of the Windows Installer runtime. Users will have this if they have Windows XP SP2. Even so, it means that installing your simple DLL or Exe might require a patch, a restart, and local admin rights.
Another option is to use static linking for the runtime library. This means using /MT rather than /MD. Note that this can change the behaviour of your code; in fact, Microsoft advises: "it is not recommended to link statically to the CRT in a DLL unless the consequences of this are specifically desired and understood." The other snag is that if a security problem is found in the runtime library, and patched, your application will not get the benefit of the patch.
The third option, of course, is to use another compiler. Some people prefer Visual C++ 6.0 because it links to the standard msvcrt.dll, which is pretty much guaranteed to be present on all 32-bit versions of Windows, though you could hit version problems (old-style DLL Hell).
I have some sympathy with Microsoft. It really is trying to solve DLL versioning issues; and some of these issues are inherently intractable. Even so, I'm not sure about the wisdom of requiring side-by-side for msvcr80.dll (and a few others). However, developers must understand these deployment issues, otherwise we'll see more error dialogs like the ones above.
...and one more thing HAPPY NEW YEAR
I've noticed an excellent post and discussion by Martyn Lovell, a member of the C++ team at Microsoft who says he owns "...libraries, which means the C and C++ runtimes and standard libraries, MFC, ATL, ATL Server, and some new libraries we're creating for managed code applications". Lovell explains the rationale behind side-by-side and highlights the recommendation not to use static linking to the runtime libraries; he also observes that Visual C++ 6.0 is now unsupported. It won't be easy, but it's our call.
If you read the discussion following Lovell's article referenced above, you'll notice that there is a documented way to install the runtime libraries without registering side-by-side assemblies:
However, if you want to install-applocal, you should make sure that your application has a manifest, and then copy the whole of this folder into your EXE directory:
I tried this when I first hit this issue and it didn't work; but that was before I embedded the manifest. It sounds to me like it should work provided that you embed the manifest. In other words, you can still get xcopy deployment to a clean Windows box. Note that this is still not a recommended approach, because the libraries will not get patched by Windows Update, though there is the possibility of a tool that searches the hard drive for all instances of an insecure library.
Comments are closed
Recent postsUsers plead with Borland to give up .NET
IE7 to be released 18th October,...
If Microsoft doesn't use UAC, why...
Google's unsettling lack of direction
Vista security: now prove it