CLR2 скомпилированный C# COM не работает с.Net 4
Кто-нибудь знает, почему созданная C# библиотека COM, которая была скомпилирована в CLR2 (.Net 3.5), не работает при использовании только с CLR4(.Net 4)? Чего не хватает в CLR4, который есть в CLR2 для COM?
Мы используем соответствующий запуск в app.config для запуска C# под CLR4/.Net 4:
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
Все C# работает, пока не попробует создать наш интерфейс COM. Это обеспечило следующее исключение:
Не удалось загрузить среду выполнения. (Исключение из HRESULT: 0x80131700)
Та же проблема возникает при попытке создать интерфейс COM из C++.
Как только мы устанавливаем CLR2 (.Net 3.5), все компоненты COM начинают работать. Мы хотели бы знать, что происходит.
3 ответа
После компиляции сборок в.NET 4 вам, вероятно, потребуется использовать regasm.exe для обновления RuntimeVersion. Если перекомпиляция не возможна, вы можете изменить RuntimeVersion в реестре с v2.0.50727 на v4.0.30319. Это сработало для меня. Я нашел похожий ответ здесь: Использование COM-DLL, нацеленной на.NET-2.0, в GAC в системе.NET-4-only
Сборка зарегистрирована с требованием CLR v2, но вы явно запретили загрузку этой версии с файлом.config. Вам понадобится дополнительный бит в файле.config, чтобы сказать: "Я знаю, но это нормально". Как это:
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>
Обратите внимание, что вы намеренно обходите встроенную функцию параллельного управления версиями, которая была добавлена в.NET 4. Новая функция, явно добавленная, чтобы позволить приложению загружать несколько версий CLR для поддержки COM-серверов, которые имеют разные Требования к версии CLR. Что, безусловно, звучит как ваш сценарий. В этом случае более совместимая ловушка мыши позволяет загружать обе версии CLR:
<startup>
<supportedRuntime version="v4.0"/>
<supportedRuntime version="v2.0.50727"/>
</startup>
Другая очень важная деталь - это имя и расположение этого файла.config. Это не интуитивно понятно, но CLR находит файл.config из каталога и имя запуска EXE. Поэтому, если вы тестируете этот [ComVisible] сервер из собственной программы на C++, скажем, c:\foo\bar.exe, то вы должны дать имя файлу "bar.exe.config" и скопировать его в каталог c: \ foo. Поместить файл.config в тот же каталог, что и DLL с именем DLL, не получится.
Версия CLR записывается в заголовке файла.dll, а ее значение копируется в реестр утилитой regasm. Затем активатор пытается запустить компонент с точной указанной версией CLR. Чтобы CLR 4 запускал компоненты, реализованные в сборках CLR 2, вы можете либо вручную изменить регистрационную информацию (Classes/{clsid}/InprocServer32/component-version/RuntimeVersion), либо установить useLegacyV2RuntimeActivationPolicy
как описано в предыдущем ответе (файл конфигурации действительно идет рядом с собственным.exe, в этом нет ничего плохого).