Конференция "Corba" » Доступ к COM объекту в другом процессе
 
  • Unknown_user (22.08.10 22:07) [0]
    В запущенном процессе создается COM объект


    initialization
     TAutoObjectFactory.Create(ComServer, TFileZapper, Class_FileZapper,
       ciSingleInstance, tmApartment);
    end.



    Вопрос. Как получить доступ к нему из другого процесса?
  • sniknik © (23.08.10 09:39) [1]
    популярный пример по подключению/созданию к екселю
    var
     Excel: OLEVariant;
    ...
     try
       Excel := GetActiveOleObject('Excel.Application');
     except
       Excel := CreateOleObject('Excel.Application');
     end;
  • Unknown_user (23.08.10 11:56) [2]
    А если таких одинаковых запущенных процессов несколько и мне нужно подключиться к COM объекту, находящимся в процессе с заданным PID?
  • sniknik © (23.08.10 13:52) [3]
    у модели tmApartment не может быть "запущенных процессов несколько", может быть только один, с кучей потоков по одному на подключение.
  • Сергей М. © (23.08.10 14:09) [4]

    > Unknown_user   (23.08.10 11:56) [2]


    Твой СОМ-сервер должен предусматривать некий интерфейсный метод а-ля GetProcessId, возвращающий PID.
    В условиях использования дельфийского TAutoObjectFactory это единственно верное и простое решение.

    Клиент-контроллер, желающий подключиться к нужному экз-ру твоего сервера, обращается к ROT (Running Object Table), перечисляет-фильтрует существующие объекты по известному классу COM-сервера, обращается к каждому из найденных эк-ров и вызывает GetProcessId, получая PID и сравнивая с искомым.
    Подключение же к найденному в таблице экз-ру с помощью моникера - дело плёвое.
  • Unknown_user (23.08.10 14:18) [5]
    >у модели tmApartment не может быть "запущенных процессов несколько", может быть только один, с кучей потоков по одному на подключение.

    Но есть ведь и ciSingleInstance, когда для каждого клиента создается отдельная копия объекта COM сервера.
  • Unknown_user (23.08.10 14:18) [6]
    >Сергей М.

    Спасибо, буду разбираться.
  • Unknown_user (23.08.10 14:20) [7]
    >Подключение же к найденному в таблице экз-ру с помощью моникера - дело плёвое.

    А какой VCL класс реализует это?
  • Сергей М. © (23.08.10 15:08) [8]

    > какой VCL класс реализует это?
    >


    Из стандартных - никакой.
    Из сторонних - не в курсе.
    Но все это хоз-во реализуется достаточно просто непосредственно с использованием WinAPI.
  • Unknown_user (24.08.10 14:54) [9]
    >Сергей М

    Спасибо за подсказки. Реализовал немного иначе. Задача у меня была создать MDI приложение, где каждое дочернее окно - отдельный процесс.

    Я создал объект COM автоматизации. Метод Get_DrawWindow этого объекта при первом вызове создает окно. Это окно представляет дочерний процесс.

    Вызов фабрики классов производится следующим образом

     Factory := TAutoObjectFactory.Create(ComServer, TChild, Class_Child,
      ciSingleInstance, tmApartment);



    где TChild - coclass интерфейса IChild.

    Регистрация интерфейсов производится здесь же, если соответствующий ключ в реестре не найден

    if not Regisred then ComServer.UpdateRegistry(True);



    Каждое обращение к объекту Child вызывает запуск процесса, который его содержит. А это этот же EXE. Проверить запускается дочерний процесс или основной можно по наличию ключа -EMBEDDING или -AUTOMATION в командной строке. С этим ключом Windows запускает процессы с объектами автоматизации.

    Есть одно но. Если в процессе запущена фабрика классов, первое создание компонентного объекта не вызывает запуск дочернего процесса. Происходит это потому, что как фабрика классов работает в этом же процессе и в нем же создает экземпляр объекта. Последующие создания экземпляров компонентного объекта вызывают запуски дочерних процессов, по одному на объект (включен режим ciSingleInstance).

    Самое простое решение проблемы - это останавливать фабрику классов, если запущен основной процесс (нет ключа -EMBEDDING в командной строке).

    Чувствую, что правильнее самому запускать дочерние процессы из основного, регистрировать COM объекты в ROT и подключаться к ним из основного процесса. Так как вы советовали. Минус моего подхода - обязательная регистрация интерфейсов в реестре. Для этого для учетной записи из под которой запущено приложение нужны права администратора.

    В общем, идея имеет право на жизнь. Многопроцессное приложение возможно. Коммуникацию между процессами легко реализовать при помощи COM.

    Если кому интересно, выложу исходники.
  • Unknown_user (26.08.10 13:34) [10]
    >Сергей М.

    Подскажите, пожалуйста. Переделал подключение к дочерним процессом, согласно вашему алгоритму.

    >Клиент-контроллер, желающий подключиться к нужному экз-ру твоего сервера, обращается к ROT (Running Object Table), перечисляет-фильтрует существующие объекты по известному классу COM-сервера, обращается к каждому из найденных эк-ров и вызывает GetProcessId, получая PID и сравнивая с искомым.

    Однако имеется проблема. RegisterActiveObject не дает занести в ROT больше одного объекта с заданным CLSID. В итоге могу запустить и подключиться только к одному дочернему процессу. Как-то можно это обойти?
  • 6x8 (26.08.10 14:18) [11]
  • Unknown_user (26.08.10 15:43) [12]
    >6x8  

    Спасибо. Работает!
 
Конференция "Corba" » Доступ к COM объекту в другом процессе
Есть новые Нет новых   [134427   +35][b:0][p:0.001]