Simplify Visual C++ Application Deployment with Manifest Files

Introduction

The control library that ships with Windows is undoubtedly the most widely used component library that has ever shipped, and when this high usage is combined with the great time span that Windows has been shipping, the compatibility challenge for the control libraries of Windows is very difficult to address. The wonderful MSDN blog of Raymond Chen give some background into the challenges and solutions of Windows control compatibility that lead to the development of manifest files and their sibling technology of side-by-side (SxS) assemblies.

The basic premise of SxS assembly deployment is that once an application has been developed and tested against a particular version of Windows common controls, the application should continue to operate against the same version of these controls for the lifetime of that application version. No matter how insignificant or internal a change that a shared library has from one version to the next, the likelihood that some applications will be broken by the change is very high. Rather than requiring each application to imperatively call an API to request a common control version, a declarative XML mechanism know as manifest files was introduced to allow applications to specify the common control version that they want to use. The manifest can either be a simple XML file with the name of the application and a .manifest file extension that is located in the same directory as the executable, or it can be embedded in the application as a resource.

The dependency information contained in a manifest file is fairly simple, and is essentially a list of dependant assemblies along with version information. To request that version 6 of Windows Common Controls is used, the manifest would be as simple as:

  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <dependency>
      <dependentAssembly>
        <assemblyIdentity 
          type="win32" 
          name="Microsoft.Windows.Common-Controls" 
          version="6.0.0.0" 
          processorArchitecture="x86" 
          publicKeyToken="6595b64144ccf1df" 
          language="*">
        </assemblyIdentity>
      </dependentAssembly>
    </dependency>
  </assembly>
Listing 1. Manifest SxS settings

  • From its fairly meager beginnings describing assembly dependencies, the utility of the application manifest is increasing, and Windows Vista and Window 7 have introduced a number of new manifest file elements unrelated to SxS features. As the software virtualization and application management features continue to increase in importance, the use of manifest files to specify the operating environment that an application expects and requires for stability and performance will increase. Some of the newer settings that can now be controlled via the application manifest file are:

  • User Access Control (UAC) level required by the application. For applications that require full administrator privileges to execute correctly, the manifest file is the correct place to request that Windows prompts the user for privilege escalation.
  • ClickOnce applications. For ClickOnce application (which are applications that have a simplified install and update life-cycle, and rely less on the traditional heavy-weight MSI based installer approach), the application itself is actually described by the manifest file. In addition to the dependency elements, ClickOnce applications are required to specify an entryPoint element that details the assembly and command line arguments that are required to launch the application, and a trustInfo element that details the application's security requirements. Visual C++ 2010 does not support integrated ClickOnce manifest production from within the IDE, but this MSDN article has detailed information about the steps required.
  • DPI Virtualization. Windows will run an application in a virtualized window if high DPI support has been enabled at the operating system level and an application's manifest file does not indicate that the application is high-DPI aware. The DPI virtualization leads to some fuzziness of display (similar to running a monitor as a non-native resolution), so developing applications that handle high DPI correctly and indicating this in the manifest file is a worthwhile investment.
  • Compatibility settings. Every version of Windows has changes in the way various OS features operate. This is to be expected, as improving the performance and stability is one of the key selling points of any software upgrade. Unfortunately, these improvements can cause some applications that have been built with an implicit expectation of the previous behavior to crash or behave incorrectly, and if this problem is widespread or heavily reported, users and organizations appetite for a Windows upgrade can be severely curtailed. As this is a very similar problem to the SxS issues that initially prompted the introduction of manifest files, it makes sense that the manifest file specifies the operating system version behavior that an application is expecting.

    To achieve this, Windows 7 introduces a new compatibility manifest element that can be used to opt-in to new Windows 7 behavior. If an application's manifest file does not contain this element or the element does not nominate Windows 7 as a supported OS, Windows Vista behavior will occur. The full list of features controlled by this setting is listed in the SDK documents, and the actual manifest setting to activate Windows 7 behavior is:

  <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> 
    <application> 
      <!--The ID below indicates application support for Windows 7 -->
        <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
        </application> 
      </compatibility>
  </assembly>
Listing 2. Compatibility Manifest Settings



Visual C++ 2010 provides support for generating manifest files as part of the build and link process. Figure 1 shows the various Property Pages available for Manifest settings in a Visual C++ project. Most of the options available in this tool map to command line arguments that can be passed to the Manifest SDK tool (mt.exe) that ships as part Windows SDK. In addition to supporting traditional manifest file options related to SxS settings, the production of manifest files for managed assemblies and the native SxS assemblies themselves in also supported.

Visual C++ Project Manifest Properties
Figure 1. Visual C++ Project Manifest Properties

Outside of the SxS settings, the UAC settings that are emitted in the manifest file are controlled by Linker | Manifest properties page shown in Figure 2. The UAC Execution Level specifies the permissions that the application requires for execution, and UAC Bypass UI Protection settings specifies whether the application requires interaction with high permission desktop windows like the on-screen keyboard.

Figure 2.  UAC Manifest Settings for a Visual C++ Application
Figure 2. UAC Manifest Settings for a Visual C++ Application

Visual C++ 2010 does not support the newer Windows 7 compatibility settings, but these settings can be specified by providing an additional input file to the manifest tool as shown in Figure 3. The additional input file should include the root assembly element and any additional elements that need to be merged with the output of the inbuilt manifest tool. The XML in Listing 2 would be sufficient to achieve this.

 Specifying additional manifest files
Figure 3. Specifying additional manifest files

To confirm that the settings have been processed by the build process and included in the embedded manifest file, the binary image can be opened inside Visual C++ 2010, and the manifest resource can be inspected as shown in Figure 4.

Inspecting the embedded manifest file
Figure 4. Inspecting the embedded manifest file

Conclusion

The management features and virtualization support that Windows provides for an application is continuing to grow, and the manifest file has become the central location for an application to specify the operating environment that is required for successful and efficient operation. Visual C++ provides good support for specifying various options that are incorporated into the manifest files, and for settings that have no inbuilt tool support, and additional manifest file can be provided.

Related Articles