Как заставить COM без регистрации работать в управляемом / неуправляемом взаимодействии

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

  •  28-10-2019
  •  | 
  •  

Вопрос

У меня есть неуправляемый внутрипроцессный COM-объект C ++ / ATL (в Unmanaged.dll), который я пытаюсь использовать из управляемой библиотеки C # DLL (Managed.dll). Однако я хочу использовать COM без регистрации. У меня есть следующие шаги:

  • Зарегистрируйте COM-объект на компьютере разработчика. Внутренний сервер должен иметь правильно зарегистрированную библиотеку типов.
  • Добавьте ссылку на COM-объект в проекте C #, а затем установите для свойства ссылки значение Isolated= True.

В результате создаются Unmanaged.dll, Managed.dll и Native.Managed.manifest. Открыв манифест, довольно ясно, как система использует его для загрузки COM-объекта без регистрации.

Вот в чем проблема. У меня есть управляемый EXE (Managed.exe), который динамически загружает Managed.dll для доступа к общедоступным типам. Под «динамически» я подразумеваю то, что он использует Assembly.LoadFrom («Managed.dll»). Когда код внутри Managed.dll пытается создать COM-объект, он получает исключение «класс не зарегистрирован». Похоже, контекст активации неправильно настраивается при загрузке Managed.dll.

Есть ли способ получить бесплатную регистрацию COM для работы в этом сценарии?

Это было полезно?

Решение

Два дня без ответа, вот что я придумал за это время ...

Действительно похоже, что контекст активации настраивается ОС при запуске процесса на основе манифеста, связанного с основным EXE. Это означает, что все элементы, связанные с COM, не требующие регистрации, должны находиться в файле Main.exe.manifest во время запуска процесса. Это нарушает изоляцию между EXE и DLL. Если DLL отвечает за создание COM-объектов, вы не ожидаете, что манифест EXE должен содержать информацию COM без регистрации. Вы могли ожидать, что манифест, связанный с DLL, будет объединен с контекстом активации процесса в момент загрузки DLL, но этого не произошло.

Чтобы обойти эту проблему, DLL должна настроить новый контекст активации перед созданием COM-объекта. Что еще хуже, в настоящее время (начиная с .NET 4.0) нет управляемого способа сделать это. Таким образом, DLL должна будет вызвать следующие функции Win32:

Я заключил эти вызовы в управляемый класс, который вызывает CreateActCtx и ActivationActCtx в конструкторе, а DeativateActCtx и ReleaseActCtx в IDisposable :: Dispose.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top