Как SXS выбирает, какую версию фреймворка следует загрузить?

В настоящее время я работаю над тем, чтобы сборки .NET (с классами COM) работали без регистрации. Это работает хорошо, однако у меня есть одна проблема, которую я не могу точно определить.

Моя проблема в том, что привязка сборки не выполняется для правильной версии .NET Framework.

В настоящее время у меня есть 2 сборки (назовем их A.dll и B.dll), и обе они созданы с использованием .NET 4.0.

B.dll очень маленький, я сделал его для проверки активации без регистрации. Рядом с ним есть манифест, B.dll.manifest). Он содержит 1 класс с 1 свойством и 1 методом.

A.dll намного сложнее, подписанный, его манифест встраивается как ресурс как событие после сборки (с использованием mt.exe).

Я сделал приложение VB6, чтобы проверить их. В моем приложении есть манифест, в котором объявляются зависимости.

Если я запускаю свое приложение, B.dll работает хорошо, а A.dll - нет. Просматривая журналы привязки с помощью fuslogvw.exe, я обнаружил, что привязка A.dll выполняется с использованием .NET 2.0, а B.dll — с использованием .NET 4.0.

A.dll завершается ошибкой с кодом ошибки 0x8013101b, то есть COR_E_NEWER_RUNTIME. ERR: ошибка при извлечении импорта манифеста из файла (hr = 0x8013101b).

Чтобы заставить его работать, я должен добавить файл .config в свое приложение VB6 с этим содержимым.

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

Затем он привязывается к правильной версии фреймворка и работает.

Я подозреваю, что, возможно, MT.exe изменил атрибуты/метаинформацию в моей сборке, заставив ее думать, что она должна быть загружена с 2.0. Поэтому я открыл его с помощью ILSpy. Все, что я там вижу, говорит о 4.0 и ничего подозрительного.

Я читал, что сборка по умолчанию должна быть загружена с использованием прошивки, которая использовалась для их сборки (в моем случае они ВСЕ 4.0, нигде нет 2.0). Итак, я не понимаю, ПОЧЕМУ он пытается загрузить именно этот, используя 2.0.

Это проблема для меня, так как я хотел бы избежать необходимости создавать/обслуживать, но, прежде всего, РАЗВЕРНУТЬ эти .config для всех приложений, которые будут использовать эту конкретную сборку. В моем конкретном случае это означало бы наличие около 100 файлов .config.

Для справки:

Я использовал MT.exe из SDK 7.0A версии 5.2.3790.2076.

Вот вывод fuslogvw.exe (извините за французский и запутанный акцентированный символ, в любом случае важной частью является номер версии фреймворка)

Б, рабочий

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.

А, не работает

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, работает (благодаря файлу конфигурации)

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.

person Carl Quirion    schedule 05.09.2013    source источник
comment
Думая, что это могло быть из-за mt.exe, я изменил свое событие после сборки, чтобы создать только манифест и пропустить встраивание (оставив мою сборку нетронутой). Я все еще получаю ту же ошибку. Попытался перейти на более новую версию MT (ту, которая поставляется с SDK 8.1), и это тоже не помогло.   -  person Carl Quirion    schedule 05.09.2013
comment
Обнаружил, что в моей сборке есть ссылки на более старые сборки 2.0. Я удалил их, чтобы проверить. Тот же результат, поэтому моя проблема не в ссылках.   -  person Carl Quirion    schedule 05.09.2013


Ответы (1)


М. Миллер из команды CLR указал мне правильное направление. В моем манифесте (созданный mt.exe из Windows SDK 7.0A) не было значения в runtimeVersion тега clrClass.

Это приводило к тому, что загрузчик CLR попадал в «ограниченный» путь загрузки. Этот ограниченный путь загрузки, который, как сказал мне М. Миллер, происходит, когда версия не v4 или выше, и он ограничивает значение, возвращаемое загрузчиком «FindLatestVersion», до v2. Поэтому он пытается загрузить сборки, используя микропрограмму 2.0.

Изменение манифеста для указания правильной версии (v4.0.30319) и проверка того, что ничего не кэшируется (мне пришлось скопировать каталог куда-то еще, чтобы правильная версия отображалась в журналах), в итоге решили мою проблему. Теперь загрузка идет по правильному пути, а не по пути «с ограничением».

Так что это оказалось простой проблемой манифеста.

FWIW, я попытался сгенерировать тот же манифест, используя mt.exe из Windows SDK 8.1 (последний), и он правильно сгенерировал атрибут runtimeVersion!

Я хотел бы поблагодарить Марка Миллера за его помощь в этом вопросе, без его помощи мне потребовалось бы время, чтобы понять это!

person Carl Quirion    schedule 05.09.2013
comment
О механизме кэширования я нашел эту запись в блоге. Кэширование делает отладку ошибочного манифеста очень сложной. Эта запись в блоге содержит обходной путь csi-windows.com/blog/all/27-csi-news-general/ - person Carl Quirion; 06.09.2013
comment
Рад, что смог помочь. Ключевым моментом здесь было то, что COM без регистрации использовался для регистрации CLSID, а манифест не включал строку версии, которую прокладка использует для определения подходящей среды выполнения. Обычная регистрация с помощью RegAsm или других инструментов генерирует ключи реестра с правильной строкой версии, и, по-видимому, mt.exe (по крайней мере, последняя версия) также получает это право. Обратите внимание, что это версия среды выполнения, аналогичная строкам версии, используемым для элемента конфигурации supportRuntime, а не маркетинговым версиям, используемым для .NET (3.5, 4.5 и т. д.). - person Mark Miller; 07.09.2013
comment
Да, последний (SDK 8.1) файл mt.exe действительно содержит правильную версию среды выполнения. Однако установленный под 7.0А - нет. Просто предостережение всем, кто пытается использовать его для создания манифестов Reg-Free COM. - person Carl Quirion; 09.09.2013