The famous "Could not load file or assembly or one of its dependencies" error message

If you have ever done any software development under Microsoft Windows you have probably come across this famous error message: "System.IO.FileNotFoundException : Could not load file or assembly 'Acme.dll' or one of its dependencies. The specified module could not be found." 

Modern software makes heavy use of dynamic link libraries, and the problem with this kind of libraries is that for various reasons they might not be there when you need them, resulting in runtime errors. This is the runtime error you get under Windows when this happens.

Naturally, when you see this message, the first thing to do is to check whether Acme.dll is there, and what you usually discover is that the file is indeed there. When dealing with computers, most error messages that you come across tend to leave some room for troubleshooting, but when the system is reporting that a certain file does not exist on your very own filesystem, while the file is most certainly there, the situation seems really hopeless. You are stymied. 

(Useful pre-reading: About these papers)

At this point you are likely to start shot-gunning the problem by trying various random tricks in the hope that one of them will magically make the problem go away: you try running the application again just in case it was a glitch, you try obtaining a fresh copy of the library in case this one somehow got corrupted, you restart Windows because we always try that, right? -- and none of these attempts yields any results.

Finally, when you have exhausted all other possibilities, you decide to take a closer look at the error message again. You notice that it says that it could not load Acme.dll "or one of its dependencies", so you start with a new hypothesis: what cannot be found is not Acme.dll itself, it is one of the libraries that Acme.dll in turn tries to load. But which one? The next sentence says "the specified module could not be found", but which module is the specified module? There is only one module being named in the error message, and that is Acme.dll, so this must be the specified module, right?

What is happening here is that this error message is a notorious instance of trolling with which Microsoft has been torturing software professionals for decades now by telling them lies instead of reporting the actual problem. The problem is indeed that one of the dependencies of the library in question could not be found, but Windows will not tell you which one. Instead, it will give you this insidiously worded message which will send you looking for the problem in wrong directions.  

There is probably some programmer who worked at Microsoft some 30 years ago and is probably a pensioner by now, who has a permanent evil grin on his face knowing that he has personally caused millions of work hours wasted all over the planet over the course of several decades simply by creating this particular error message in this particular way. (Or, perhaps, he told his manager that the task he was working on would need to take a little longer because he had to collect all necessary information to produce a useful error message, and his manager told him to not do that because deadlines.)

To fix this problem you have to use some special software called a "Dependency Analyzer" to trace all the dependencies of your application and locate the one that fails to load.

The msvcr100.dll sub-problem

Quite often the dependency analyzer finds that the culprit is msvcr100.dll or something similar, which you might be completely unaware of. This msvcr100.dll is the dynamically linkable runtime library for software written using some old version of Microsoft Visual C++, which is a very popular language for writing all sorts of software under Windows, so if your application is using any third-party libraries, then one or more of them have almost certainly been written in MSVC. For some reason, many developers of libraries choose to make their product depend on an external instance of the MSVC runtime library instead of statically linking the MSVC runtime library into their product, and this creates an extra moving part which must be dealt with by others, like you.

What is especially treacherous about msvcr100.dll in particular is that most large commercial applications contain it and install it in your Windows/System32 folder, so once you have installed a few commonly used apps on your machine you almost certainly have msvcr100.dll. This causes two major problems:

  • You are completely oblivious to the fact that the application that you are developing indirectly depends on msvcr100.dll without including it in its own installer. You only discover this problem when you try to run your application on a relatively fresh installation of Windows. 
  • Not only you are oblivious about the msvcr100.dll problem, but also, the developers of libraries that you use might also be oblivious to it. For example, HDF5DotNet.dll is a popular library used by DotNet applications for reading and writing HDF5 files. This library depends on msvcr100.dll but does not include it in its installable package, nor is there any mention in their documentation about the fact that msvcr100.dll must be present in order for their library to successfully load.

Note that an msvcr100.dll with a size of 773968 bytes may exist under C:\Windows\SysWOW64, but it may not necessarily be the one you need. Your application might instead depend on another msvcr100.dll with a size of 829264 bytes under C:\Windows\System32.

The approach recommended by Microsoft for solving this kind of problem is to include the "Microsoft Visual C++ Redistributable" installable package, and install it as part of the application's installation process.  An easier way is to simply include a copy of msvcr100.dll in the directory from which your application launches.

No comments:

Post a Comment