Exploring Manifests Part 2: Default Namespaces and UAC Manifests in Windows Vista


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.

Comments (15)

  1. Adrian Silasi says:

    Well done, this is the best solution I’ve seen so far indeed.

    Many thanks,

    Adrian

  2. I wanted to write something quick about how modifying the default Visual Studio 2005 manifest file with…

  3. Adrian Accinelli says:

    Looks like there are two versions of mt.exe shipping with VS2005.  The newer version 6.0.4071.0 seems to properly handle the merging of trustinfo without the nasty side effect on Windows XP.

    The "working" version lives in <VS2005 root folder>Common7ToolsBin.  If you copy it into the <VS2005 root folder>VCbin folder then your standard VC compile will suddenly work with or without Chris Jackson’s excellent solution.

    Not sure what the other side effects from this change in version are yet.

  4. Good workaround.

    Thanks very much.

    George

  5. One of the many reasons why I love my job so much is that I am so consistently faced with problems that

  6. fro says:

    Hello,

    Do you know how to successfully merge Visual 2005 auto-generated manifest, and another one that I create?

    I tried doing that to add the requestedExecutionLevel tag, using the "User Account Control for Game Developers" DirectX SDK example, but I get this error:

    "general error c1010070: Failed to load and parse the manifest."

    Thanks.

  7. cjacks says:

    Are you sure you have a valid manifest?

    These are the results for this error code:

    # anonymous HRESULT: Severity: FAILURE (1), Facility 0x101, Code 0x70

    # for hex 0x70 / decimal 112

     SESSION4_INITIALIZATION_FAILED                                 bugcodes.h

     NMERR_NOT_TRANSMIT                                             netmon.h

     OLEUI_ERR_DIALOGFAILURE                                        oledlg.h

     ERROR_DISK_FULL                                                winerror.h

    # There is not enough space on the disk.

    The example above is a merge of one I generated with the VS2005 "behind the back" one, we just need to figure out where things are going awry. You can also try using mt.exe to get some granularity on what you’re doing and potentially assist your investigation.

  8. Shay No says:

    Thanks for your help,

    I add to my mainifest the following:

    <appname>.exe.Manifest

     <trustInfo>

       <security>

         <applicationRequestMinimum>

           <PermissionSet Unrestricted="true" ID="Custom" SameSite="site" />

           <defaultAssemblyRequest permissionSetReference="Custom" />

         </applicationRequestMinimum>

       </security>

     </trustInfo>

     <ms_asmv2:trustInfo xmlns:ms_asmv2="urn:schemas-microsoft-com:asm.v3">

       <ms_asmv2:security>

         <ms_asmv2:requestedPrivileges>

           <ms_asmv2:requestedExecutionLevel level="asInvoker"></ms_asmv2:requestedExecutionLevel>

         </ms_asmv2:requestedPrivileges>

       </ms_asmv2:security>

     </ms_asmv2:trustInfo>

    Good luck guys.

  9. Riani says:

    Hi,

    I try to embed a manifest into c# application using vs 2005. But I have difficulties in define the post-build event. I define it as below:

    "$C:….VCbinmt.exe" -manifest "$D:workspace2005testnettest$nettest.exe.manifest"  –outputresource:"$D:workspace2005testnettestnettestbinRelease$nettest.exe";#1

    but I keep get this following error message :

    The system cannot find the path specified.

    C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Microsoft.Common.targets(3089,13): error MSB3073: The command ""$C:….VCbinmt.exe" -manifest "$D:workspace2005testnettest$nettest.exe.manifest"  –outputresource:"$D:workspace2005testnettestnettestbinRelease$nettest.exe";#1" exited with code 3.

    could please you help me?

    thanks in advance.

  10. cjacks says:

    Hi Riani,

    I’d get Process Monitor to have a look and see what it can’t find. Filter on mt.exe.

    (We now also natively support manifests in Visual Studio 2008 – makes it much easier!)

    Thanks,

    Chris

  11. Hari says:

    There is a extra $ in the path. See your command line is correct. See in your error string "$D:" which is not a valid path

  12. casylius says:

    With Visual Studio 2008, this embedding UAC manifest can be done easily with the Project Properties -> Application pane click on the “View UAC Settings” button, and change the setting that you need

  13. casylius says:

    On My VS2008 Team System, the option is specified under "Specified how application resource will be managed" – select the "manifest" edit box and select the manifest file that you defined for the app "<App.EXE>.manifest".  

    Also in VS2008, the mt.exe was not present.

  14. yani says:

    hi,

    ‘m trying to create a manifest file in order to set the setting for UAC in Vista.

    I already refer to msdn document. If I want to develop codes that need to be run in Vista and XP, I need to use the notes for-Building and Embedding a Manisfest with Microsoft Visual Studio 2005 for Windows Xp and Windows Vista Applications.

    This is my manifest file.

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

     <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>

    But when I run, I got this error message:

    general error c1010070:failed to load and parse the manifest.

    FYI, I already go to Project Properties-Linker-Generate Manifest – NO.

    Beside that, I also change at Project Properties-Manifest Tool-Input and Output-Additional Manifest File (i type the manifest file name).

    Any ideas about this?

    thanks.

    -izyani@yahoo.com

  15. suman says:

    Hi casylius,

    There is an issue with auto generating UAC manifest with Visual Studio 2008.  IT hard codes the version and name as follows:

    <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />

    This is reported to MS but the resolution was not clear:

    http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=290160

    What "setting on the project" update this version? If anyone know then please post it here.