2009-10-04

Applications that have embedded manifests and use the .NET CLR may fail to load their configuration files on Windows Server 2003

This is one of those amazingly obscure bugs. If you have a .NET application with an embedded manifest running on Windows Server 2003, it may fail to find its configuration file, causing all sorts of problems. The workaround is to make sure the manifest includes a non-empty <dependency> section.

If you have an application that seems to fail this way, you can verify you are the victim of this bug by renaming the configuration file so that it only ends in .config rather than .exe.config. For exampe, if you have Foo.exe.config, rename it to Foo.config and you should at least be able to find things like appSettings again. Because some code (both internal and external) may expect that the configuration file name ends in .exe.config, this is not exactly a fix.

Normally .NET applications do not have a manifest. Only if you're writing unmanaged applications that load the CLR explicitly (using CorBindToRuntimeEx) or when you are writing C++/CLI mixed-mode applications can you embed a manifest (to suppress UAC prompts on Windows Vista and Windows Server 2008, most like). Furthermore, if your application links to the MFC, CRT or ATL libraries dynamically (the default), you will not run into this bug as you will have a nonempty <dependency> section in your manifest.

The only assembly I have found that will be installed on all versions of Windows that properly support side-by-side assemblies (Windows XP SP2 forward) is version 6 of the Common Controls library. Add a new .XML file to your project that contains the following:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <!-- This is a dummy dependency required to work around the bug in the Windows Server 2003 executable loader where it refuses to see the .config file if the embedded manifest has an empty <dependency> section. -->
      <assemblyIdentity 
        type="win32"
        name="Microsoft.Windows.Common-Controls"
        version="6.0.0.0"
        processorArchitecture="*"
        publicKeyToken="6595b64144ccf1df"
        language="*" />
    </dependentAssembly>
  </dependency>
</assembly>

Now go to your project properties and add this file under Manifest Tool → Input and Output → Additional Manifest Files and rebuild your project. It should now run properly on Windows Server 2003.

1 comment:

Anonymous said...

YOU SAVED MY LIFE! I've been working on this problem for about a day now, and I was not making any progress... Excellent write-up.