I suppose we all know about how some software sometimes “just doesn’t work”… It requires some kind of software package or update or whatnot to be installed, but you have no idea what. For us developers it may be a tad simpler… There is this tool called Dependency Walker, to help us figure out what DLLs it is trying to load and where it is failing.
However, this is not that easy to use for a regular end-user. Firstly, it requires the user to know about this utility. Secondly, it requires the user to understand and use the utility (which requires basic knowledge of DLL mechanics, not that trivial.. Functions, symbols, ordinals, delay-load… what?). Lastly, even for us developers, Dependency Walker isn’t a total solution. It can tell us what we’re missing, but only in vague terms of DLL filenames or function symbol names. It doesn’t give us an actual name for the product/download/update which will include the missing DLLs.
In my case, with a 3D engine that can run on Windows XP, Vista, 7, DirectX 9, 10, 11, and in both 32-bit and 64-bit, and me using the latest development tools, I also run into the problem that my software sometimes “just doesn’t work” on another machine, and I need Dependency Walker to figure out why. This gave me the idea to implement my own lightweight Dependency Walker functionality, and embed it into my executable. I had already moved the main engine code into a DLL, because that made it easier for me to select the proper codepath for a machine at runtime. I now try to load the DLL, and if it fails, I scan its import tables to figure out why not. Unlike Dependency Walker however, I actually try to give the user some hints on what to install. It can look something like this:
In this case I’ve tried running my engine on XP with the D3D9 engine DLL missing. This way it tries the D3D11 and D3D10 DLLs, and when it can’t find anything that works, it will give the analysis. As you can see, it reports various missing DLLs. If the DLLs existed, but were missing certain functions, it would also report that. It actually tests all imported functions of every DLL recursively. Because it finds that a DLL with “d3d11” in the name is missing, it displays the following hint to the end-user:
“Direct3D 11 not found. Use Windows 7 or Windows Vista with Service Pack 2 and the Vista Platform Update installed.”
That’s a custom message that I put in there, which should steer the user in the right direction. The process is repeated when it sees that “d3d10” is missing as well, with another custom message:
“Direct3D 10 not found. Use Windows 7 or Windows Vista with Service Pack 1 installed.”
In theory you can add any kind of custom messages for any pattern of missing DLL filenames and/or missing functions that you detect. You could also take it further and detect the Windows version that the user is using… So if he has XP, you can tell him he needs to upgrade to Vista or Windows 7 to get D3D10/11… If he has Vista, he’d just need to install the proper updates. In the end there could be an entire library of DLLs and what package they belong to, making it very easy for the end-user to locate everything he needs. You could even give the actual download URLs. Detecting the missing functions and DLLs for the application was the hard part. Now that we have a tool to do that for us, we know what is missing, and we just have to categorize missing DLLs and functions into the different pieces of software that they belong to, and present the information to the end-user in a way that allows him to fix the problem.
The best part of this is ofcourse that the routines are all open source, under the BSD license. So anyone can use them in their own application. They are part of the CPUInfo project, and can be found in the Windows/Dependencies subdirectory. I hope more people will use it in the future.