Dépannage d'applications isolées C/C++ et d'assemblys côte à côte

Le chargement d'une application C/C++ peut échouer si les bibliothèques Visual C++ dépendantes sont introuvables. Une liste d'erreurs d'exécution potentielles se trouve dans Redistribution des fichiers Visual C++. Dans cette section, les raisons les plus courantes d'échec du chargement d'une application C/C++ sont décrites avec des suggestions d'étapes pour résoudre les problèmes.

Si une application est déployée sur un ordinateur où Visual C++ n'est pas installé et qu'elle s'arrête avec les messages d'erreur semblables à ceux répertoriés dans Redistribution des fichiers Visual C++, plusieurs choses sont à vérifier pour comprendre la raison de l'erreur.

  1. Suivez les étapes décrites dans Fonctionnement des dépendances d'une application Visual C++. Le Dependency Walker peut afficher la plupart des dépendances d'une application ou DLL spécifique. Si vous constatez que certaines DLL sont manquantes, installez-les sur l'ordinateur sur lequel vous tentez d'exécuter votre application.

  2. Le chargeur de système d'exploitation utilise un manifeste pour charger des assemblys dont dépend votre application. Il peut être soit incorporé dans le fichier binaire en tant que ressource, soit enregistré comme fichier externe dans le dossier local de l'application. Pour savoir si le manifeste est incorporé dans le fichier binaire, ouvrez ce dernier dans Visual Studio et examinez ses ressources. Vous devez être en mesure de trouver une ressource nommée RT_MANIFEST. Si vous ne pouvez pas trouver de manifeste incorporé dans le fichier binaire, recherchez un fichier externe dont le nom serait du type <binary_name>.<extension>.manifest.

  3. Si aucun manifeste n'est présent, vous devez veiller à ce que l'éditeur de liens génère un manifeste pour votre projet. Vous devez vérifier l'option Génération d'un manifeste de l'éditeur de liens dans la boîte de dialogue Propriétés du projet pour ce projet.

    Notes

    La construction de projets Visual C++ sans génération de manifeste n'est pas prise en charge. Tout programme C/C++ généré à partir de Visual C++ doit inclure un manifeste qui décrit ses dépendances sur les bibliothèques Visual C++.

  4. Si le manifeste est incorporé dans le fichier binaire, vérifiez que l'ID de RT_MANIFEST est correct pour ce type de fichier binaire. Pour les applications, l'ID doit être égal à 1 et pour la plupart des DLL, l'ID doit être égal à 2. Si le manifeste se trouve dans un fichier externe, ouvrez-le depuis un éditeur XML ou un éditeur de texte. Pour plus d'informations sur les manifestes et les règles de déploiement, consultez Manifestes.

    Notes

    Sous Windows XP, si un manifeste externe est présent dans le dossier local de l'application, le chargeur du système d'exploitation l'utilise à la place du manifeste incorporé dans le fichier binaire. Sous Windows Server 2003 et les versions ultérieures de Windows, c'est le contraire qui est vrai : le manifeste externe est ignoré et le manifeste incorporé est utilisé lorsqu'il existe.

  5. Il est préférable que toutes les DLL aient un manifeste incorporé dans le fichier binaire. Les manifestes externes sont ignorés lorsqu'une DLL est chargée via un appel à LoadLibrary. Pour plus d'informations, consultez Manifestes d'assembly.

  6. Vérifiez que tous les assemblys énumérés dans le manifeste sont correctement installés sur l'ordinateur. Chaque assembly est spécifié dans le manifeste par son nom, son numéro de version et son architecture de processeur. Si votre application dépend d'assemblys côte à côte, vérifiez que ceux-ci sont correctement installés sur l'ordinateur, afin que le chargeur du système d'exploitation puisse les rechercher en suivant les étapes spécifiées dans Séquence de recherche d'assemblys. N'oubliez pas que les assemblys 64 bits ne peuvent pas être chargés dans les processus 32 bits ni exécutés sur les systèmes d'exploitation 32 bits.

Exemple

Supposons que nous avons une application, appl.exe, créée avec Visual C++. Le manifeste de cette application est soit incorporé à appl.exe comme ressource binaire RT_MANIFEST avec un ID égal à 1, soit stocké comme fichier externe, appl.exe.manifest. Le contenu du manifeste peut ressembler à ceci :

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

Ce manifeste indique au chargeur du système d'exploitation qu'appl.exe dépend d'un assembly nommé Microsoft.VC90.CRT, version 9.0.xxxxx.y et créé pour une architecture de processeur x86 32 bits.

L'assembly côte à côte dépendant peut être installé comme un assembly partagé ou comme un assembly privé. Par exemple, Visual Studio 2008 installe l'assembly CRT en tant qu'assembly côte à côte partagé qui se trouve dans le répertoire %WINDIR%\WinSxS\x86_Microsoft.VC90.CRT_<version> sous Windows XP ou dans le répertoire %WINDIR%\winsxs\x86_microsoft.vc90.crt_<version> sous Windows Vista.

Le assembly manifest pour un assembly CRT Visual C++ partagé est également installé dans %WINDIR%\WinSxS\Manifests\x86_microsoft.vc90.crt_<version>.manifest sous Windows XP ou dans %WINDIR%\winsxs\Manifests\x86_microsoft.vc90.crt_<version>.manifest sous Windows Vista. Il identifie cet assembly et répertorie son contenu (DLL qui font partie de cet 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>

Les assemblys côte à côte peuvent également utiliser lesfichiers de configuration d'éditeur, également appelés fichiers de stratégie, pour rediriger globalement des applications et des assemblys afin qu'ils utilisent une autre version du même assembly à la place d'une version d'assembly côte à côte. Vous pouvez activer des stratégies pour l'assembly CRT Visual C++ partagé dans %WINDIR%\WinSxS\Policies\x86_policy.9.0.Microsoft.VC90.CRT_<version>.policy sousWindows XP ou dans %WINDIR%\winsxs\Manifests\x86_policy.9.0.microsoft.vc90.crt_<version>.manifest sous Windows Vista, dont le contenu est semblable au suivant :

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

La stratégie ci-dessus spécifie qu'une application ou un assembly quelconque qui demande la version  9.0.aaaaa.bbb de cet assembly doit utiliser à la place la version 9.0.xxxxx.yy de ce même assembly, qui est la version actuellement installée sur le système. Si une version de l'assembly mentionné dans le manifeste d'application est spécifiée dans le fichier de stratégie, le chargeur recherche une version de cet assembly spécifiée dans le manifeste dans le dossier WinSxS, et si cette version n'est pas installée, le chargement échoue. De même, si la version 9.0.xxxxx.yy de l'assembly n'est pas également installée, le chargement échoue pour les applications qui demandent la version 9.0.aaaaa.bbb de l'assembly.

Toutefois, l'assembly CRT peut également être installé comme assembly côte à côte privé dans le dossier local de l'application. Si le système d'exploitation ne trouve pas le CRT ni aucun autre assembly sous la forme d'un assembly partagé, il se met à rechercher l'assembly sous la forme d'un assembly privé. Il recherche les assemblys privés dans l'ordre suivant :

  1. Cherchez dans le dossier local de l'application un fichier manifeste portant le nom <assemblyName>.manifest. Dans cet exemple, le chargeur recherche Microsoft.VC90.CRT.manifest dans le même dossier qu'appl.exe. Si le manifeste est trouvé, le chargeur charge la DLL CRT depuis le dossier de l'application. Si la DLL CRT est introuvable, le chargement échoue.

  2. Essayez d'ouvrir le dossier <assemblyName> dans le dossier local d'appl.exe et, s'il existe, chargez le fichier manifeste <assemblyName>.manifest depuis ce dossier. Si le manifeste est trouvé, le chargeur charge la DLL CRT depuis le dossier <assemblyName>. Si la DLL CRT est introuvable, le chargement échoue.

Consultez Séquence de recherche d'assemblys pour une description plus détaillée de la façon dont le chargeur recherche des assemblys dépendants. Si le chargeur ne trouve pas d'assembly dépendant sous la forme d'un assembly privé, le chargement échoue et « Le système ne peut pas exécuter le programme spécifié » s'affiche. Pour corriger cette erreur, les assemblys et les DLL dépendants qui en font partie doivent être installés sur l'ordinateur en tant qu'assemblys privés ou partagés.

Voir aussi

Concepts

Concepts d'applications isolées et d'assemblys côte à côte

Autres ressources

Génération d'applications isolées C/C++ et d'assemblys côte à côte