I was going to create a post about how to embed manifests into your Visual Studio solution, but Catherine Heller has already covered that topic quite thoroughly. These techniques were quite useful on XP, as you could use them to create an application that voted itself in to the side-by-side assembly comctl.dll version 6 (which enabled visual styles). With Windows Vista, they become even more important, as this is the technique you use to express your intentions regarding UAC. Do you want to run as a standard user? Do you want to run as an administrator? Do you want to run with the highest available token?

What I want to explore today are some of the side effects that you may not expect from manifests that you include in your application, and techniques that you may want to use to avoid some of the less desirable side-effects.

Developer Best Practices and Guidelines for Applications in a Least Privileged Environment discusses the User Account Control feature in Windows Vista, and about half way down the document (it's quite a long one) it provides a sample manifest for specifying that you would like your application to run as an administrator. You can easily modify this sample manifest to either of the other two values (asInvoker or highestAvailable) and deploy it with your application.

However, let's say that you did exactly that. Include a similar manifest, and include elements to opt into visual styles. Here is the manifest that we will begin with:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" processorArchitecture="*" version="1.0.0.0" name="MyApplication.exe"/>
  <description>My totally awesome application</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" language="*" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" />
    </dependentAssembly>
  </dependency>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

Now, since I am using Visual C++ 2005, I can use the manifest tools included with Visual Studio to embed this manifest. You may assume that this is the manifest that you will see in the final executable. However, if you use the mt.exe tool to pull the manifest out of your executable and view it, it appears to have changed! Here is what I found:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" processorArchitecture="*" version="6.0.0.0" name="MyApplication.exe"></assemblyIdentity>
  <description>My totally awesome application</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" language="*" processorArchitecture="*" publicKeyToken="6595b64144ccf1df"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2" xmlns="urn:schemas-microsoft-com:asm.v2">
    <ms_asmv2:security xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker"></requestedExecutionLevel>
      </requestedPrivileges>
    </ms_asmv2:security>
  </ms_asmv2:trustInfo>
</assembly>

Interesting, no? Unexpected? But if you take a look at the final manifest, you'll see that the build process is just doing exactly the same thing that you are trying to do - specify side by side assemblies. It is specifying a particular version of the C runtime assembly. If I were to have extracted it from the debug build, then it would have specified the debug version of this assembly.

However, if you look carefully at the XML, you will notice that some other things have changed. Specifically, take a look at the namespaces around the trustInfo element. In the manifest that we input into the merge process, we redefined the default namespace to use the v2 version of the asm namespace. This is perfectly valid XML, and the redefinition expires when we move back up a level. However, the merge process apparently wanted to be more explicit, and so it inserted a namespace qualifier. It also happened to leave the default namespace redeclaration, which isn't necessary. Then, the first child redefines this namespace again. This may be undesirable - can we avoid this?

There are a number of solutions floating around the web right now. One is to not include the asm.v2 elements at build time, crack the exe with mt.exe, extract the manifest, add the trustInfo element and its children, and then stuff it back into the executable with these changes using mt.exe. There are even some scripts available to automate this as a post-build step. Another approach is to not include the default manifest, so that there is nothing to merge (and if you never perform a merge, you never get any side-effects of the merge process). The problem with this approach is that you are no longer voting into any side-by-side assemblies that you may need, such as the C runtime, MFC, ATL, etc.

However, I thought this was a rather cumbersome solution. Isn't there a simpler way? It seemed to me that, if the problem is that it doesn't like the redefinition of the default namespace, why don't we just not redefine the default namespace in the first place and see if the merging process likes that better?

It turns out that it does.

If I feed in the following manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" processorArchitecture="*" version="1.0.0.0" name="MyApplication.exe"/>
  <description>My totally awesome application</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" language="*" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" />
    </dependentAssembly>
  </dependency>
  <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
    <ms_asmv2:security>
      <ms_asmv2:requestedPrivileges>
        <ms_asmv2:requestedExecutionLevel level="asInvoker"/>
      </ms_asmv2:requestedPrivileges>
    </ms_asmv2:security>
  </ms_asmv2:trustInfo>
</assembly>

This is the merged manifest that I see on the other end:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" processorArchitecture="*" version="6.0.0.0" name="MyApplication.exe"></assemblyIdentity>
  <description>My totally awesome application</description>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" language="*" processorArchitecture="*" publicKeyToken="6595b64144ccf1df"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC80.CRT" version="8.0.50608.0" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
  <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v2">
    <ms_asmv2:security>
      <ms_asmv2:requestedPrivileges>
        <ms_asmv2:requestedExecutionLevel level="asInvoker"></ms_asmv2:requestedExecutionLevel>
      </ms_asmv2:requestedPrivileges>
    </ms_asmv2:security>
  </ms_asmv2:trustInfo>
</assembly>

As a result, I still get a full merge of any dependent side-by-side assemblies, I include my trustInfo, and I no longer have a duplicate namespace which could cause disasterous results on XP. Much easier! So, I would just avoid redeclaring the default XML namespace in your manifests, and you should be much happier with the outcome of the merge process.