-
Unknown_user (22.08.10 22:07) [0]В запущенном процессе создается COM объект
initialization
TAutoObjectFactory.Create(ComServer, TFileZapper, Class_FileZapper,
ciSingleInstance, tmApartment);
end.
Вопрос. Как получить доступ к нему из другого процесса? -
популярный пример по подключению/созданию к екселю
var
Excel: OLEVariant;
...
try
Excel := GetActiveOleObject('Excel.Application');
except
Excel := CreateOleObject('Excel.Application');
end; -
Unknown_user (23.08.10 11:56) [2]А если таких одинаковых запущенных процессов несколько и мне нужно подключиться к COM объекту, находящимся в процессе с заданным PID?
-
у модели 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
Спасибо. Работает!