Dela via


Troubleshooting C/C++ Isolated Applications and Side-by-side Assemblies

Loading a C/C++ application can fail if dependent Visual C++ libraries cannot be found. A list of potential runtime errors can be found in Redistributing Visual C++ Files. In this section the most common reasons for a C/C++ application failing to load are described, with proposed steps to resolve the problems.

If an application is deployed on a computer without Visual C++ installed, and it crashes with error messages similar to those listed in Redistributing Visual C++ Files, several things have to be checked to understand the reason for the error.

  1. Follow the steps described in Understanding Dependencies of a Visual C++ Application. The dependency walker can show most dependencies for any particular application or DLL. If you see that some DLLs are missing, install those DLLs on the computer on which you are trying to run your application.

  2. A manifest is used by the operating system loader to load assemblies that your application depends on. It can either be embedded inside the binary as a resource, or saved as an external file in the application's local folder. To check whether the manifest is embedded inside the binary, open your binary in Visual Studio and browse through the resources of this binary. You should be able to find a resource named RT_MANIFEST. If you cannot find a manifest embedded inside the binary, check for an external file named something like <binary_name>.<extension>.manifest.

  3. If a manifest is not present, you need to ensure that the linker generates a manifest for your project. You need to check the linker option Generate manifest in the Project Properties dialog for this project.

    Note

    Building Visual C++ projects without manifest generation is not supported. Any C/C++ program built in Visual C++ has to include a manifest describing its dependencies on Visual C++ libraries.

  4. If the manifest is embedded inside the binary, ensure that the ID of RT_MANIFEST is correct for this type of the binary. For applications, ID should be equal to 1, for most DLLs ID should be equal to 2. If the manifest is in an external file, open it in an XML editor or text editor. For more information on manifests and rules for deployment, see Manifests.

    Note

    On Windows XP, if an external manifest is present in the application's local folder, the operating system loader uses this manifest instead of a manifest embedded inside the binary. On Windows Server 2003 and later versions of Windows, the opposite is true—the external manifest is ignored and the embedded manifest is used when present.

  5. It is recommended that all DLLs have a manifest embedded inside the binary. External manifests are ignored when a DLL is loaded though a LoadLibrary call. For more information, see Assembly manifests.

  6. Check that all assemblies enumerated in the manifest are correctly installed on the computer. Each assembly is specified in the manifest by its name, version number and processor architecture. If your application depends on side-by-side assemblies, check that these assemblies are installed on the computer properly, so they can be found by the operating system loader using the steps specified in Assembly Searching Sequence. Remember that 64-bit assemblies cannot be loaded in 32-bit processes and cannot be executed on 32-bit operating systems.

Example

Assume we have an application, appl.exe, built with Visual C++ 2005. This application has its manifest either embedded inside appl.exe as a binary resource RT_MANIFEST with ID equal to 1, or stored as an external file, appl.exe.manifest. The content of the manifest may be something like this:

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.xxxxx.y" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>

To the operating system loader this manifest says that appl.exe depends on an assembly named Microsoft.VC90.CRT, version 9.0.xxxxx.y and built for 32-bit x86 processor architecture.

The dependent side-by-side assembly can be installed as either a shared assembly or as a private assembly. For example, Visual Studio 2005 installs the CRT assembly as a shared side-by-side assembly which can be found in the directory %WINDIR%\WinSxS\x86_Microsoft.VC90.CRT_<version> when running Windows XP or in the directory %WINDIR%\winsxs\x86_microsoft.vc90.crt_<version> when running Windows Vista.

The assembly manifest for a shared Visual C++ CRT assembly is also installed in %WINDIR%\WinSxS\Manifests\x86_microsoft.vc90.crt_<version>.manifest when running Windows XP or in %WINDIR%\winsxs\Manifests\x86_microsoft.vc90.crt_<version>.manifest when running Windows Vista and it identifies this assembly and lists its contents (DLLs that are part of this assembly):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <noInheritable/>
   <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
   <file name="msvcr90.dll" hash="3ca5156e8212449db6c622c3d10f37d9adb12c66" hashalg="SHA1"/>
   <file name="msvcp90.dll" hash="92cf8a9bb066aea821d324ca4695c69e55b27cff" hashalg="SHA1"/>
   <file name="msvcm90.dll" hash="7daa93e1195940502491c987ff372190bf199395" hashalg="SHA1"/>
</assembly>

Side-by-side assemblies can also use publisher configuration files, also called policy files, to globally redirect applications and assemblies from using one version of a side-by-side assembly to another version of the same assembly. You can check policies for the shared Visual C++ CRT assembly in %WINDIR%\WinSxS\Policies\x86_policy.9.0.Microsoft.VC90.CRT_<version>.policy when running Windows XP or in %WINDIR%\winsxs\Manifests\x86_policy.9.0.microsoft.vc90.crt_<version>.manifest when running Windows Vista, which contains something like this:

</assembly>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!-- Copyright © 1981-2001 Microsoft Corporation -->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">

   <assemblyIdentity type="win32-policy" name="policy.9.0.Microsoft.VC90.CRT" version="9.0.xxxxx.yy" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
   <dependency>
      <dependentAssembly>
         <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"/>
         <bindingRedirect oldVersion="9.0.aaaaa.bbb-9.0.ccccc.d" newVersion="9.0.xxxxx.yy"/>
      </dependentAssembly>
   </dependency>
</assembly>

The policy above specifies that any application or assembly that asks for version 9.0.aaaaa.bbb of this assembly should instead use version 9.0.xxxxx.yy of this assembly, which is the current version installed on the system. If a version of the assembly mentioned in the application's manifest is specified in the policy file, the loader looks for a version of this assembly specified in the manifest in the WinSxS folder, and if this version is not installed, load fails. And if an assembly version 9.0.xxxxx.yy is not installed as well, load fails for applications that ask for assembly version 9.0.aaaaa.bbb.

However, the CRT assembly can also be installed as a private side-by-side assembly in the application's local folder. If the operating system fails to find the CRT or any other assembly as a shared assembly, it starts looking for the assembly as a private assembly. It searches for private assemblies in the following order:

  1. Check the application local folder for a manifest file with name <assemblyName>.manifest. In this example, the loader tries to find Microsoft.VC90.CRT.manifest in the same folder as appl.exe. If the manifest is found, the loader loads the CRT DLL from the application folder. If the CRT DLL is not found, load fails.

  2. Try to open folder <assemblyName> in appl.exe's local folder and if it exists, load manifest file <assemblyName>.manifest from this folder. If the manifest is found, the loader loads the CRT DLL from <assemblyName> folder. If the CRT DLL is not found, load fails.

See Assembly Searching Sequence for a more detailed description of how the loader searches for dependent assemblies. If the loader fails to find a dependent assembly as a private assembly, load fails and "The system cannot execute the specified program" is displayed. To resolve this error, dependent assemblies and DLLs that are part of them must be installed on the computer as either private or shared assemblies.

See Also

Concepts

Concepts of Isolated Applications and Side-by-side Assemblies

Other Resources

Building C/C++ Isolated Applications and Side-by-side Assemblies