Имитация SideBySide для внепроцессного ActiveX

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

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

И вот почти часть: в настоящий момент наше приложение вызывает (из его части на 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 удаленное взаимодействие и вернемся ко второму процессу.

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

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

person Alex Shnayder    schedule 14.01.2010    source источник


Ответы (2)


Это возможно. Что нужно:

  • Приложению необходимо запустить сам сервер, а не полагаться на COM. Вам не нужно дополнительное косвенное обращение, обеспечиваемое реестром, просто используйте CreateProcess ().
  • Сервер должен зарегистрировать свои фабрики классов в своем методе main () с помощью CoRegisterClassObject ().
  • Важно: CLSID, который он использует для каждой фабрики, следует изменить, чтобы он был уникальным для каждого экземпляра службы. Это гарантирует, что клиент подключается к правильному серверу. Я просто выполняю XOR ID процесса с CLSID фабрики классов. Клиент также знает идентификатор процесса, поэтому может внести такие же изменения.
  • Приложение должно вызвать CoCreateInstance () в цикле с вызовом Sleep (), чтобы дождаться появления фабрики объектов. Не объявляйте неудачу, пока не пройдет не менее 60 секунд (это меня укусило).
  • И приложению, и серверу нужен манифест, содержащий <file> элемент для каждой прокси / заглушки DLL и <comInterfaceExternProxyStub> элементы для каждого удаленного интерфейса.
person Hans Passant    schedule 14.01.2010
comment
Поправьте меня, если я ошибаюсь, но ваше предложение не использует ObjectFromLresult, как я предложил правильно? О CoRegisterClassObject, где именно он его регистрирует, как мое приложение сможет найти его с помощью CoCreateInstance, если он не зарегистрирован в реестре, даже если он есть в манифесте? - person Alex Shnayder; 17.01.2010
comment
Это не. CoCreateInstance () найдет его в таблице запущенных объектов. - person Hans Passant; 17.01.2010
comment
Большое спасибо, если бы не ваша помощь, мне бы понадобилось немало времени, чтобы заставить его работать. - person Alex Shnayder; 20.01.2010
comment
У меня проблема с приведением к реализованному интерфейсу, я получаю эту ошибку при операции приведения HRESULT: 0x80004002 (E_NOINTERFACE). Что не имеет смысла, потому что мой объект реализует соответствующий интерфейс, и я могу получить доступ к методам интерфейса по имени из клиентского приложения через отражение, любые идеи? - person Alex Shnayder; 20.01.2010
comment
Это может иметь какое-то отношение как к клиенту, так и к серверу, реализованным с использованием .net, предоставит дополнительную информацию, как только я буду уверен на 100%. - person Alex Shnayder; 06.02.2010
comment
Как выбираются прокси и заглушки при использовании этого решения? - person codeshot; 21.01.2017
comment
Есть ли какой-то подсчет ссылок, который можно сделать, чтобы я мог избежать использования тайм-аута в дочернем или родительском процессе, чтобы дождаться завершения инициализации и обнаружить неудачную инициализацию? - person codeshot; 21.01.2017
comment
Есть ли способ обеспечить доступность фабричного объекта на протяжении всего жизненного цикла родительского процесса и предоставить ссылку на дочерний процесс, чтобы ребенок оставался живым в течение этого периода, но выходил сразу после этого? - person codeshot; 21.01.2017

Алекс,

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

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

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

WebUpdate: IAutomation;

WebUpdate: = CoAutomation.Create; ‹- Ошибка не работает


WebUpdate: Variant;

WebUpdate: = CreateOleObject ('WebUpdate.Automation'); <-- Работает отлично

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

Давай, рис!

person Community    schedule 23.03.2010
comment
Я не эксперт по Delpi, но насколько я понимаю, инфраструктура Delphi com имеет сильную связь с тем, что на самом деле зарегистрировано в реестре и присутствует в библиотеках типов (особенно в той, в которой выполняется код), поэтому она довольно эффективна для неэффективности SxS. . Но это верно только в отношении интерфейсов, а не объектов. Мы смогли обойти это ограничение, объединив ROT и относительную регистрацию интерфейсов и библиотек типов (не CoClasses). - person Alex Shnayder; 25.03.2010
comment
Под относительным я подразумеваю, что в реестре мы помещаем не весь путь к библиотеке, а только. \ LibName.dll, так что каждый процесс может ожидать найти libName.dll в своей собственной папке. libName.dll может быть даже самим процессом, так что вы можете без проблем ссылаться на свои собственные интерфейсы с помощью в коде. - person Alex Shnayder; 25.03.2010