Имитация SideBySide для ActiveX вне процесса - PullRequest
3 голосов
/ 15 января 2010

Мы адаптируем наше относительно сложное приложение на стороне клиента (ActiveX / .net / Delphi / C ++ / COM) для использования SxS для обеспечения развертывания без прав администратора и изоляции от более старых версий нашего продукта.

Мы смогли достичь этой цели почти для всех наших компонентов in proc, таких как .net ui, Delphi ui и COM-серверы, которые мы используем в proc, путем создания файла манифеста, в котором описаны все библиотеки, используемые нашим процессом, без регистрации на клиенте какого-либо из компонентов (почти).

И вот идет почти часть: В настоящее время наше приложение вызывает (из своей части c ++) сервер ActiveX вне процесса (Delphi ActiveX EXE), который, в свою очередь, сам вызывает другой набор серверов вне ActiveX (сторонние плагины, любая вещь здесь, Delphi, C ++, любая вещь, если она не работает с ActiveX EXE и реализует наши интерфейсы).

Как мы знаем SxS не поддерживает внешние серверы ActiveX. И мы не можем использовать эти объекты, как в proc com серверах в нашем основном процессе, потому что это потребует серьезной переписки нашего приложения и, что еще хуже, перерыва нашего общедоступного API, который используется сторонними инструментами и поставщиками, API перерыв, который мы не можем допустить.

Мы наткнулись на эту статью , в которой описывается, как IHTMLDocument2 можно извлечь из окна Internet Explorer, запущенного в отдельном процессе. Что заставило нас задуматься об этом подходе:

Мы создали бы вторичное спутниковое приложение / процесс, который будет запускать ActiveX как на сервере процессов. Затем мы будем использовать LresultFromObject и ObjectFromLresult для передачи ссылки на объект ActiveX из спутникового приложения в основной процесс приложения. Спутниковое приложение будет иметь собственный файл манифеста, который позволит ему работать в режиме SxS.

Такой же подход будет использоваться для связи между этим Delphi ActiveX EXE и сторонними плагинами AciveX EXE

Существует альтернативное решение, которое на данный момент мы не предпочитаем предложенному выше решению, которое заключается в использовании классов прокси .net remoting и .net com для открытия канала связи между двумя процессами путем перевода запроса com в .net remoting и обратно на com на второй процесс.

Итак, возникает вопрос:

  1. Что вы думаете об этом подходе?
  2. Видите ли вы лучшее решение проблемы?

Ответы [ 2 ]

4 голосов
/ 15 января 2010

можно сделать. Что нужно:

  • Приложение должно запускать сам сервер, а не полагаться на COM. Вам не нужно дополнительное косвенное указание реестра, просто используйте CreateProcess ().
  • Сервер должен зарегистрировать свои фабрики классов в своем методе main () с помощью CoRegisterClassObject ().
  • Важно: CLSID, который он использует для каждой фабрики, должен быть изменен, чтобы быть уникальным для каждого экземпляра службы. Это гарантирует, что клиент подключается к правильному серверу. Я просто XOR ID процесса с фабрикой классов CLSID. Клиент также знает идентификатор процесса, поэтому может внести те же изменения.
  • Приложение должно вызывать CoCreateInstance () в цикле с вызовом Sleep (), чтобы дождаться появления фабрики объектов. Не объявляйте провал, пока не прошло как минимум 60 секунд (что меня укусило).
  • И приложению, и серверу нужен манифест, содержащий элемент <file> для каждой DLL-библиотеки-посредника / заглушки и <comInterfaceExternProxyStub> для каждого удаленного интерфейса.
0 голосов
/ 24 марта 2010

Alex

nobugz прав, вы можете получить доступ к таблице запущенных объектов, чтобы создать экземпляр COM-объекта из текущего запущенного процесса вашей Delphi Automation Exe.

Однако я обнаружил большую проблему, которую не могу объяснить. При работе таким способом я могу получить доступ к объекту только через метод диспетчеризации вариантов.

Обычно, если мой Active X exe не зарегистрирован, я получаю ошибку «Интерфейс не поддерживается», если я пытаюсь создать экземпляр объекта через интерфейсы, например:

WebUpdate: IAutomation;

WebUpdate: = CoAutomation.Create; <- Ошибка при работе </p>


WebUpdate: Variant;

WebUpdate: = CreateOleObject ('WebUpdate.Automation'); <- Отлично работает </p>

Если я зарегистрирую активный x exe с помощью regserver, проблема исчезнет !!

Пойди!

...