2013-09-05 2 views
1

Je travaille actuellement sur l'obtention des assemblys .NET (avec des classes COM) pour travailler sans inscription. Cela fonctionne bien, mais j'ai un problème dont je n'arrive pas à identifier la cause exacte.Comment SXS choisit-il quelle version de l'infrastructure doit être chargée?

Mon problème est que la liaison d'assembly n'est pas effectuée sur la version .NET Framework correcte.

J'ai actuellement 2 assemblages (appelons-les A.dll et B.dll) et ils sont tous deux construits en utilisant .NET 4.0. B.dll est très petit, je l'ai fait pour tester l'activation sans enregistrement. Il a un manifeste à côté, B.dll.manifest). Il contient 1 classe avec 1 propriété et 1 méthode.

A.dll est beaucoup plus complexe, signé, il est manifeste est incorporé comme une ressource en tant qu'événement post-construction (en utilisant mt.exe).

J'ai fait une application VB6 pour les tester. Mon application a un manifeste, qui déclare les dépendances.

Si je cours mon application, B.dll fonctionne bien mais A.dll ne fonctionne pas. En regardant les journaux de liaison avec fuslogvw.exe, j'ai trouvé que la liaison de A.dll est tentée en utilisant .NET 2.0, tandis que B.dll est fait en utilisant .NET 4.0.

A.dll échoue avec le code d'erreur 0x8013101b, qui est COR_E_NEWER_RUNTIME. ERR: Erreur lors de l'extraction de l'importation manifeste à partir du fichier (hr = 0x8013101b).

Pour le faire fonctionner, je dois ajouter un fichier .config à mon application VB6 avec ce contenu

<?xml version="1.0"?> 
<configuration> 
    <startup useLegacyV2RuntimeActivationPolicy="true" > 
     <supportedRuntime version="v4.0" /> 
    </startup> 
</configuration> 

Ensuite, il se lie à la bonne version du cadre et il fonctionne. J'ai pensé que peut-être, MT.exe a changé les attributs/méta-informations dans mon Assemblée, en faisant croire qu'il devrait être chargé avec 2.0. Donc, je l'ai ouvert en utilisant ILSpy. Tout ce que je vois là-bas parle de 4.0 et rien n'est suspect. J'ai lu que l'assembly devrait être chargé, par défaut, en utilisant le FW qui a été utilisé pour construire em (dans mon cas, ils sont ALL 4.0, no 2.0 n'importe où). Donc, je ne comprends pas pourquoi il essaie de charger celui en particulier en utilisant 2.0.

Ceci est un problème pour moi car je voudrais éviter de devoir créer/maintenir mais surtout DEPLOY ces .config pour toutes les applications qui vont utiliser cet assembly particulier. Cela voudrait dire environ 100 fichiers .config, dans mon cas particulier.

Pour référence:

Le mt.exe i utilisé est du SDK 7.0a et est la version 5.2.3790.2076.

Voici le fuslogvw.sortie exe (désolé pour le français et l'foiré omble accentué, la partie importante est le numéro de version du framework de toute façon)

B, travaillant

JRN : cette liaison démarre dans le contexte de chargement de default. 
JRN : tentative de téléchargement du fichier de configuration de l'application à partir de file:///C:/RegFreeCom/BafComClient/binTB/Project1.exe.config. 
JRNÂ : Le fichier de configuration C:\RegFreeCom\BafComClient\binTB\Project1.exe.config n'existe pas. 
JRN : aucun fichier de configuration de l'application n'a été trouvé. 
JRN : utilisation du fichier de configuration d'hôte : 
JRN : utilisation du fichier de configuration de l'ordinateur à partir de C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. 
JRN : stratégie non appliquée à la référence à ce stade (liaison d'assembly privée, personnalisée, partielle ou basée sur l'emplacement). 
JRN : tentative de téléchargement de la nouvelle URL file:///C:/RegFreeCom/BafComClient/binTB/sidebysidenet.DLL. 
JRN : le téléchargement de l'assembly a réussi. Tentative d'installation du fichier : C:\RegFreeCom\BafComClient\binTB\B.dll 
JRN : entrée dans la phase d'installation à exécution à partir de la source. 
JRN : le nom de l'assembly est : B, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null 
JRN : la liaison a réussi. Elle retourne un assembly à partir de C:\RegFreeCom\BafComClient\binTB\B.dll. 
JRN : l'assembly est chargé dans le contexte de chargement default. 

A, ne fonctionne pas

JRN : cette liaison démarre dans le contexte de chargement de default. 
JRN : tentative de téléchargement du fichier de configuration de l'application à partir de file:///C:/RegFreeCom/BafComClient/binTB/Project1.exe.config. 
JRNÂ : Le fichier de configuration C:\RegFreeCom\BafComClient\binTB\Project1.exe.config n'existe pas. 
JRN : aucun fichier de configuration de l'application n'a été trouvé. 
JRN : utilisation du fichier de configuration de l'ordinateur à partir de C:\Windows\Microsoft.NET\Framework\v2.0.50727\config\machine.config. 
JRN : référence post-stratégie : A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=SomeToken, processorArchitecture=MSIL 
JRN : échec de la recherche dans le GAC. 
JRN : tentative de téléchargement de la nouvelle URL file:///C:/RegFreeCom/BafComClient/binTB/A.DLL. 
JRN : le téléchargement de l'assembly a réussi. Tentative d'installation du fichier : C:\RegFreeCom\BafComClient\binTB\A.dll 
JRN : entrée dans la phase d'installation à exécution à partir de la source. 
ERR : erreur lors de l'extraction de l'importation du manifeste à partir du fichier (hr = 0x8013101b). 
ERR : impossible de terminer l'installation de l'assembly (hr = 0x8013101b). Détection terminée. 

A , travaillant (grâce au fichier de configuration)

JRN : cette liaison démarre dans le contexte de chargement de default. 
JRN : tentative de téléchargement du fichier de configuration de l'application à partir de file:///C:/RegFreeCom/BafComClient/binTB/Project1.exe.Config. 
JRN : le fichier de configuration de l'application a été trouvé (C:\RegFreeCom\BafComClient\binTB\Project1.exe.Config). 
JRN : utilisation du fichier de configuration de l'application : C:\RegFreeCom\BafComClient\binTB\Project1.exe.Config 
JRN : utilisation du fichier de configuration d'hôte : 
JRN : utilisation du fichier de configuration de l'ordinateur à partir de C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config. 
JRN : référence post-stratégie : A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=SomeToken, processorArchitecture=MSIL 
JRN : échec de la recherche dans le GAC. 
JRN : tentative de téléchargement de la nouvelle URL file:///C:/RegFreeCom/BafComClient/binTB/A.DLL. 
JRN : le téléchargement de l'assembly a réussi. Tentative d'installation du fichier : C:\RegFreeCom\BafComClient\binTB\A.dll 
JRN : entrée dans la phase d'installation à exécution à partir de la source. 
JRN : le nom de l'assembly est : A, Version=1.0.0.0, Culture=neutral, PublicKeyToken=SomeToken 
JRN : la liaison a réussi. Elle retourne un assembly à partir de C:\RegFreeCom\BafComClient\binTB\A.dll. 
JRN : l'assembly est chargé dans le contexte de chargement default. 
+0

Pensant peut-être été à cause de mt.exe, je modifié mon post-construction de l'événement pour générer uniquement le manifeste et sauter le plongement (en laissant mon assemblée intacte). Je reçois toujours la même erreur. J'ai essayé de passer à une version plus récente de MT (celle fournie avec SDK 8.1) et cela ne l'a pas résolu non plus. –

+0

J'ai trouvé des références dans mon assembly à des assemblages 2.0 plus anciens. Je les ai retirés pour le tester. Même résultat encore, donc les références ne sont pas ce qui cause mon problème. –

Répondre

1

M. Miller de l'équipe CLR m'a indiqué la bonne direction. Mon manifeste (généré par mt.exe à partir de Windows SDK 7.0A) n'incluait pas de valeur dans runtimeVersion de la balise clrClass.

C'était à l'origine du chargeur CLR pour entrer dans un chemin de chargement « plafonnés ». Ce chemin de chargement plafonné, qui, d'après ce que M. Miller m'a dit, se produit lorsqu'une version n'est pas v4 ou supérieure et qu'elle plafonne la valeur renvoyée par la propriété «FindLatestVersion» du chargeur vers v2. Donc, il essaie de charger des assemblages en utilisant le 2.0 FW.

Modifier le manifeste pour spécifier la version correcte (v4.0.30319) et s'assurer que rien n'était mis en cache (j'ai dû copier mon répertoire ailleurs, pour que la bonne version apparaisse dans les logs), a résolu mon problème. Maintenant, le chargement descend le bon chemin au lieu d'aller sur le chemin "Capped". Cela a fini par être un simple problème manifeste.

FWIW, j'ai essayé de générer le même manifeste en utilisant mt.exe à partir de Windows SDK 8.1 (dernier en date) et il a généré l'attribut runtimeVersion correctement!

Je voudrais remercier Mark Miller pour son aide à ce sujet, sans son aide, il aurait fallu un certain temps pour moi de comprendre cela!

+0

A propos du mécanisme de mise en cache, j'ai trouvé cette entrée de blog. La mise en cache rend le débogage défectueux manifeste très difficile. Cette entrée de blog contient une solution de contournement http://csi-windows.com/blog/all/27-csi-news-general/245-find-out-why-your-external-manifest-is-being-ignored –

+1

Content J'étais capable d'aider. La pièce maîtresse ici était que COM sans reg était utilisé pour enregistrer le CLSID et le manifeste n'incluait pas la chaîne de version que le shim utilise pour déterminer quel runtime est approprié. L'enregistrement typique avec RegAsm ou d'autres outils génère des clés de registre avec la bonne chaîne de version, et apparemment mt.exe (au moins le dernier) obtient ce droit aussi bien. Notez qu'il s'agit de la "version d'exécution", similaire aux chaînes de version utilisées pour l'élément de configuration supportedRuntime, et non des "versions marketing" utilisées pour .NET (3.5, 4.5, etc.) –

+0

Oui, la dernière version (SDK 8.1) La sortie de mt.exe contient en effet la bonne version de runtimeVersion. Cependant, celui installé sous "7.0A" ne le fait pas. Juste un mot d'avertissement à quiconque essaie de l'utiliser pour générer des manifestes COM sans Reg. –

Questions connexes