Yesterday, I ran into an interesting problem; I needed to give a small executable to a co-worker. However, this executable had simply been archived in a directory containing a wide variety of other programs, scripts, data files, and accumulated junk, and I really didn’t want to be overly generous by bestowing all of this detritus on my co-worker. Just to make things a little more complicated, the executable wouldn’t run by itself; it was a .NET application and had at least one, possibly as many as six, associated DLLs (I wasn’t sure how many and which ones because of the conditions under which I’d received the software).
I went to one of our developers, and he told about the ildasm tool (Intermediate Language Disassembler) included with Visual Studio 2005. This tool does a lot of stuff, but you can also use the Manifest viewer to see what DLLs a .NET application requires. In order to run it, you need to start up a command line that has the necessary application path entries; the default command prompt does not have the Visual Studio directories added to its path. However, Visual Studio creates a separate command prompt shortcut for you: Programs, Microsoft Visual Studio 2005, Visual Studio Tools, Visual Studio 2005 Command Prompt.
For whatever reason, this tool didn’t tell me what I needed to know. Just for fun, I tried opening a regular command prompt, copying my mystery executable (mystery.exe) to a temporary directory, and running it. As expected, it didn’t work and I got an error dialog box — but after I dismissed the error, I did get this intriguing response in my command prompt window:
C:\temp\mystery.exe Unhandled Exception: System.IO.FileNotFoundException: Could not load file or ass embly 'missing, Version=1.3.3718.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. File name: 'missing, Version=1.3.3718.0, Culture=neutral, PublicKeyToken=null' at STS.Mystery.Main(String args) WRN: Assembly binding logging is turned OFF. To enable assembly bind failure logging, set the registry value [HKLM\Software\M icrosoft\Fusion!EnableLog] (DWORD) to 1. Note: There is some performance penalty associated with assembly bind failure lo gging. To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fus ion!EnableLog].
Okay, that’s pretty wicked cool: Windows, through the magic of the .NET framework, is telling me how to troubleshoot the problem. I can do this! I quickly fired up Regedit and added the following value:
- Location: HKLM\Software\Microsoft\Fusion
- Name: EnableLog
- Type: DWORD
- Value: 1
With the proper registry value in place, I tried running my mystery executable one more time, and was rewarded with this:
C:\temp\>mystery.exe Unhandled Exception: System.IO.FileNotFoundException: Could not load file or ass embly 'missing, Version=1.3.3718.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified. File name: 'missing, Version=1.3.3718.0, Culture=neutral, PublicKeyToken=null' at STS.Mystery.Main(String args) === Pre-bind state information === LOG: User = DOMAIN\devin LOG: DisplayName = missing, Version=1.3.3718.0, Culture=neutral, PublicKeyToken= null (Fully-specified) LOG: Appbase = file:///C:/temp/mystery/ LOG: Initial PrivatePath = NULL Calling assembly : Mystery, Version=0.0.0.0, Culture=neutral, PublicKeyToken=nu ll. === LOG: This bind starts in default load context. LOG: No application configuration file found. LOG: Using machine configuration file from C:\WINDOWS\Microsoft.NET\Framework\v2 .0.50727\config\machine.config. LOG: Policy not being applied to reference at this time (private, custom, partia l, or location-based assembly bind). LOG: Attempting download of new URL file:///C:/temp/mystery/missing.DLL. LOG: Attempting download of new URL file:///C:/temp/mystery/missing/missing.DLL. LOG: Attempting download of new URL file:///C:/temp/mystery/missing.EXE. LOG: Attempting download of new URL file:///C:/temp/mystery/missing/missing.EXE.
Sure enough, I had a single DLL I needed to locate: missing.dll. When I coped that DLL into my temporary directory and re-ran my application, I got the errors I expected to see from not providing the proper parameters.
Problem solved! Now I could package up mystery.exe and missing.dll into a ZIP archive and send it along to my coworker.
(If you use this, don’t forget to remove the EnableLog registry key when you’re done with it – otherwise, it can lead to performance issues for .NET applications. I would think you could set it to 0 to simply disable it, but the guidance I’ve seen says to actually remove it – so that’s what I did.)