I build an executable which is dynamically linked to several DLLs. Most of these are installed by default on Windows, but maybe with slightly different versions. Others I distribute with the app, but they in turn may depend on other DLLs.
If I run the executable locally and get the Windows error message saying that "Failed to load [whatever]. The application configuration is incorrect" it seems to mean that a library that 'whatever' depends upon is missing. But it (rather infuriatingly) omits to specify exactly which DLL it was having trouble loading. Sometimes I can work this out by using Dependency Walker to see if there are any libraries that are obviously missing. Other times, I can resort to 开发者_运维知识库Process Monitor which can show me which file Windows was looking for prior to issuing the error message.
But these aren't tools that are reasonable for an end-user to have to use, when trying to diagnose their problem. Is there any way of coaxing Windows to say precisely which library it is having trouble resolving, so that this can be output to a log or displayed in a message box?
In my experience, a common cause of this kind of error is accidentally shipping a component that was linked against the debug version of the C runtime, which is explicitly not redistributable, and so it is only on an end user's system if they happen to have the matching version of VisualStudio installed. It will have a name that looks something like MSVCR80D.DLL
instead of MSVCR80.DLL
.
Dependency Walker is certainly the right tool to use to check your executable as a developer. It can hook the application for DLL load events and run it, so you can discover DLLs that are dynamically loaded at run time as well as the DLLs that were named at build time.
Dependency Walker is also scriptable, and can write a log file. I use it this way as part of my build process to validate a shipment before packaging for release. I stage all the files to be shipped into a mockup of their delivered directory tree. I use a debug mode of the application hosted by dependency walker that makes it load all its optional bits and pieces then exit. Depends.exe leaves me a nice log file, which I inspect with a Perl script and fail the build if any DLL was loaded from anywhere on the system other than \WINDOWS
or the staging area, or if an unexpected version or debug version of the C runtime was loaded. Only after that check succeeds do I build the InnoSetup installer package that will be released. This has saved embarrassment on a couple of occasions and was well worth the effort it took to figure out how to do.
If you know that every DLL is either an "official" Windows DLL or part of your shipment, then you have a really good chance of it all just working on the cusomer's machine.
Edit: The official home of Dependency Walker is a good place to poke around. The version offered there may be newer than the version included with MSVS, and there is a fair amount of decent documentation on advanced uses.
I can confirm that I have run IE profiled under depends.exe, but not tested much at all.
The windows event log usually contains some valuable information after these messages.
In XP, Right click "my computer", select "manage" and go to the "Event Viewer" there, check the system log, look for error messages which appeard about the time when the message box appeared. There should be a few of them. one of them will contain the name of the offending dll.
One technique I find useful is to create an installer project in Visual Studio (even if you don't end up shipping it). Inside your solution, create a new Setup and Deployment project and add the primary output of your project to it, then build the installer. This will do a dll dependency check phase which you'll see listed in the 'Detected Dependencies' section. So if there any dlls that you have omitted you should see them in this list.
Of course, now that you have an installer that's taken only 5 minutes to set up, you could ship that and it will deal with ensuring that the Visual Studio runtimes are setup correctly too.
精彩评论