L'application ne fonctionne pas avec les DLL VS 2008 SP1, la version précédente fonctionne avec les versions RTM

StackOverflow https://stackoverflow.com/questions/59635

  •  09-06-2019
  •  | 
  •  

Question

Depuis notre passage de Visual Studio 6 à Visual Studio 2008, nous utilisons les fichiers MFC90.dll et msvc[pr]90.dll ainsi que les fichiers manifestes dans une configuration privée côte à côte afin de ne pas nous soucier des versions. ou les installer sur le système.

Avant le SP1, cela fonctionnait bien (et fonctionne toujours bien sur nos machines de développement).Maintenant que nous avons fait quelques tests post-SP1, je m'arrache les cheveux depuis hier matin.

Tout d’abord, notre script d’installation NSIS extrait les dll et les fichiers manifestes du dossier redist.Celles-ci n'étaient plus correctes, car l'application est toujours liée à la version RTM.

J'ai donc ajouté la définition pour _BIND_TO_CURRENT_VCLIBS_VERSION=1 à tous nos projets afin qu'ils utilisent les DLL SP1 dans le dossier redist (ou les suivantes à mesure que de nouveaux service packs sortent).Il m'a fallu des heures pour trouver ça.

J'ai revérifié les fichiers manifestes générés dans le dossier des fichiers intermédiaires à partir de la compilation, et ils répertorient correctement les versions 9.0.30729.1 SP1.J'ai vérifié deux et trois fois, cela dépend d'une machine propre :tout est lié aux DLL locales sans erreur.

L'exécution de l'application génère toujours l'erreur suivante :

L'application n'a pas pu s'initialiser correctement (0xc0150002).Cliquez sur OK pour fermer l'application.

Aucune des recherches que j'ai effectuées sur Google ou Microsoft n'a abouti à quoi que ce soit en rapport avec mes problèmes spécifiques (mais il y a des retours remontant à 2005 avec ce message d'erreur).

Quelqu'un a-t-il eu un problème similaire avec le SP1 ?

Possibilités :

  • Recherchez le problème et corrigez-le pour qu'il fonctionne comme il se doit (de préférence)
  • Installer la redistribution
  • extrayez les anciennes dll et fichiers manifestes RTM et supprimez le #define pour utiliser les actuels.(Je les ai dans une version antérieure du programme d'installation, puisque Microsoft les supprime de votre dossier de redistribution !)

Modifier: J'ai essayé de reconstruire avec la définition désactivée (lien vers les DLL RTM), et cela fonctionne tant que les DLL RTM sont installées dans le dossier.Si les DLL SP1 sont ajoutées, l'erreur suivante s'affiche :

c:\Programmes\...\...\X.exe

Cette application n'a pas pu démarrer car la configuration de l'application est incorrecte.Réinstaller l'application peut résoudre ce problème.

Personne d’autre n’a-t-il eu à faire face à ce problème ?

Modifier: Juste pour sourire, j'ai téléchargé et exécuté vcredist_x86.exe pour VS2008SP1 sur ma machine de test. Il travaux.Avec les DLL SP1.Et mon application liée RTM.Mais PAS dans une distribution privée côte à côte qui fonctionnait avant le SP1.

Était-ce utile?

La solution

J'ai moi-même combattu ce problème la semaine dernière et je me considère désormais comme un expert ;)

Je suis sûr à 99% que toutes les dll et bibliothèques statiques n'ont pas été recompilées avec la version SP1.Vous devez mettre

#define _BIND_TO_CURRENT_MFC_VERSION 1
#define _BIND_TO_CURRENT_CRT_VERSION 1

dans chaque projet que vous utilisez.Pour chaque projet de taille réelle, il est très facile d'oublier une petite bibliothèque qui n'a pas été recompilée.

Il existe d'autres indicateurs qui définissent les versions auxquelles se lier ;c'est documenté sur http://msdn.microsoft.com/en-us/library/cc664727%28v=vs.90%29.aspx .Comme alternative aux lignes ci-dessus, vous pouvez également mettre

#define _BIND_TO_CURRENT_VCLIBS_VERSION 1

qui se liera à la dernière version de toutes les bibliothèques VC (CRT, MFC, ATL, OpenMP).

Ensuite, vérifiez ce que dit le manifeste intégré.Téléchargez l'éditeur de ressources XM : http://www.wilsonc.demon.co.uk/d10resourceeditor.htm.Ouvrez chaque DLL et exe de votre solution.Regardez sous « Manifeste du thème XP ».Vérifiez que l'attribut « version » sur le côté droit est « 9.0.30729.1 ».S'il s'agit de « 9.0.21022 », une bibliothèque statique récupère le manifeste de l'ancienne version.

Ce que j'ai découvert, c'est que dans de nombreux cas, les deux les versions ont été incluses dans le manifeste.Cela signifie que certaines bibliothèques utilisent la version sp1 et d'autres non.

Un excellent moyen de déboguer les bibliothèques pour lesquelles les directives du préprocesseur ne sont pas définies :modifiez temporairement les en-têtes de votre plate-forme afin que la compilation s'arrête lorsqu'elle tente d'intégrer l'ancien manifeste.Ouvrez C:\Program Files\Microsoft Visual Studio 9.0\VC\crt\include\crtassem.h.Recherchez la chaîne « 21022 ».Dans cette définition, mettez quelque chose de invalide (remplacez « définir » par « blehbleh » ou plus).De cette façon, lorsque vous compilez un projet où le _BIND_TO_CURRENT_CRT_VERSION L'indicateur du préprocesseur n'est pas défini, votre compilation s'arrêtera et vous saurez que vous devez les ajouter ou vous assurer qu'il est appliqué partout.

Assurez-vous également d'utiliser Dependency Walker afin de savoir quelles DLL sont extraites.Il est plus simple d'installer une nouvelle copie de Windows XP sans mise à jour (uniquement SP2) sur une machine virtuelle.De cette façon, vous savez avec certitude qu'il n'y a rien dans le dossier SxS qui est utilisé à la place des DLL côte à côte que vous avez fournies.

Autres conseils

Pour comprendre le problème, je pense qu'il est important de réaliser qu'il existe quatre numéros de version impliqués:

  • (A) La version des fichiers d'en-tête VC dans lesquels le .exe est compilé.
  • (B) La version du fichier manifeste intégré dans la section ressources de ce .exe.Par défaut, ce fichier manifeste est automatiquement généré par Visual Studio.
  • (C) La version des .DLL VC (qui font partie de l'assemblage côte à côte) que vous copiez dans le même répertoire que le .exe.
  • (D) La version des fichiers manifestes VC (faisant partie de l'assemblage côte à côte) que vous copiez dans le même répertoire que le .exe.

Il existe deux versions des DLL VC 2008 en cours d'exécution :

  • v1 :9.0.21022.8
  • v2 :9.0.30729.4148

Pour plus de clarté, j'utiliserai la notation v1/v2.Le tableau suivant présente un certain nombre de situations possibles :

Situation | .exe (A) | embedded manifest (B) | VC DLLs (C) | VC manifests (D)
-----------------------------------------------------------------------------
1         | v2       | v1                    | v1          | v1         
2         | v2       | v1                    | v2          | v2          
3         | v2       | v1                    | v2          | v1
4         | v2       | v2                    | v2          | v2

Les résultats de ces situations lors de l'exécution du fichier .exe sur une installation propre de Vista SP1 sont :

  • Cas 1 :une fenêtre contextuelle s'affiche indiquant :"Le point d'entrée de la procédure XYZXYZ est introuvable dans la bibliothèque de liens dynamiques".

  • Situation 2 :rien ne semble se produire lors de l'exécution du .exe, mais l'événement suivant est enregistré dans « Observateur d'événements / journal des applications » de Windows :

    La génération du contexte d'activation a échoué pour « C:\Path\file.exe ». Erreur dans le fichier manifeste ou de stratégie « C:\Path\Microsoft.VC90.CRT.MANIFEST » à la ligne 4.L'identité du composant trouvée dans le manifeste ne correspond pas à l'identité du composant demandé.La référence est Microsoft.VC90.CRT,processorArchitecture="x86",publicKeyToken="1fc8b3b9a1e18e3b",type="win32",version="9.0.21022.8".La définition est Microsoft

  • Situation 3 :tout semble bien fonctionner.C'est La solution de remicles2.

  • Situation 4 :c'est comment cela devrait être fait.Malheureusement, comme l’indique Roel, cela peut être assez difficile à mettre en œuvre.

Maintenant, ma situation (et je pense que c'est la même que Crashmstr) est le n°1.Le problème est que Visual Studio, pour une raison ou une autre, génère du code client (A) pour la v2, mais pour une raison ou une autre, génère un fichier manifeste v1 (B).Je n'ai aucune idée d'où la version (A) peut être configurée.

Note que toute cette explication s'inscrit toujours dans le contexte de assemblées privées.

Mise à jour:enfin je commence à comprendre ce qui se passe.Apparemment, Visual Studio génère le code client (A) pour la v2 par défaut, contrairement à ce que j'ai lu sur certains blogs Microsoft.L'indicateur _BIND_TO_CURRENT_VCLIBS_VERSION sélectionne uniquement la version dans le fichier manifeste généré (B), mais cette version sera ignorée lors de l'exécution de l'application.

Conclusion

Un .exe compilé par Visual Studio 2008 est lié par défaut aux versions les plus récentes des DLL VC90.Tu peux utilisez l'indicateur _BIND_TO_CURRENT_VCLIBS_VERSION pour contrôler quelle version des bibliothèques VC90 sera générée dans le fichier manifeste.Cela évite en effet la situation 2 où vous obtenez le message d'erreur "le manifeste ne correspond pas à l'identité du composant demandé".Cela explique également pourquoi la situation 3 fonctionne correctement, car même sans l'indicateur _BIND_TO_CURRENT_VCLIBS_VERSION, l'application est liée aux versions les plus récentes des DLL VC.

La situation est encore plus étrange avec les assemblys publics côte à côte, où vcredist a été exécuté, plaçant les DLL VC 9.0 dans le répertoire Windows SxS.Même si le fichier manifeste du .exe indique que les anciennes versions des DLL doivent être utilisées (c'est le cas lorsque l'indicateur _BIND_TO_CURRENT_VCLIBS_VERSION n'est pas défini), Windows ne tient pas compte ce numéro de version par défaut !Au lieu de cela, Windows utilisera une version plus récente si elle est présente sur le système, sauf lorsqu'un "fichier de configuration d'application" est utilisé.

Suis-je le seul à trouver cela déroutant ?

Donc en résumé:

  • Pour les assemblys privés, utilisez l'indicateur _BIND_TO_CURRENT_VCLIBS_VERSION dans le projet .exe et tous projets .lib dépendants.
  • Pour les assemblys publics, cela n'est pas obligatoire, car Windows sélectionnera automatiquement la version correcte des .DLL dans le répertoire SxS.

Je viens de me souvenir d'une autre astuce que j'utilisais pour découvrir quelles bibliothèques statiques se comportaient mal :'grep' via les bibliothèques statiques pour la chaîne '21022'.CEPENDANT, n'utilisez pas les outils grep "normaux" comme wingrep car ils ne vous montreront pas ces chaînes (ils pensent que c'est un fichier binaire et recherchent la chaîne brute non Unicode).Utilisez l'utilitaire « strings » du kit de ressources (maintenant sur le site Russinovich, je pense).Celui-ci parcourra les binaires, ok.Vous laissez donc ces « chaînes » parcourir toute votre arborescence source et vous verrez les fichiers binaires (dll et bibliothèques statiques) qui contiennent des références au mauvais manifeste (ou au manifeste contenant la mauvaise version).

Un autre outil intéressant pour visualiser les manifestes exe et dll est Vue du manifeste, qui, à juste titre, ne fonctionnera pas sur une nouvelle installation de XP, car il dépend de 9.0.21022.

Pour votre troisième option, vous pouvez probablement trouver les DLL et les manifestes de la version 9.0.21022 dans le répertoire C:\WINDOWS\WinSxS sur votre ordinateur de développement.Si vous le pouvez, vous pouvez configurer votre propre répertoire de redistribution et installer ces fichiers avec votre application.

Vous pouvez également utiliser ceux 9.0.30729.1 fournis avec Visual Studio et forger le manifeste que vous installez avec votre application pour signaler qu'il fournit les DLL 9.0.21022, et non 9.0.30729.1.L'éditeur de liens d'exécution ne semble pas s'en soucier.Regarde ça Blog, qui a été extrêmement utile pour résoudre ces problèmes, pour plus d'informations.

Les deux solutions de contournement ont résolu les problèmes que j'ai rencontrés lors du déploiement des DLL en tant qu'assemblys privés avec VS2008 Express.

La réponse de Roel est la voie à suivre pour votre première option ("réparez-la correctement"), mais si vous dépendez d'une bibliothèque qui dépend de 9.0.21022 (et que votre manifeste répertorie donc les deux versions), alors la troisième option peut être la seule. chemin à parcourir si vous ne souhaitez pas exécuter vcredist_x86.exe.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top