Межпроцессное взаимодействие на локальном компьютере в Windows с использованием COM

Я рассматривал вариант осуществления межпроцессного взаимодействия в Windows с использованием COM и C++.

Я нашел эту статью в MSDN, предлагающий список вариантов межпроцессного взаимодействия для Windows, и COM является одним из них.
Но, к сожалению, параметр COM просто указан без особых подробностей.

Есть ли у кого-нибудь указания о документации или других ресурсах о том, как использовать COM для межпроцессного взаимодействия в Windows?

Меня не интересует связь с удаленными машинами (поэтому: без DCOM); Меня просто интересует межпроцессное взаимодействие на одной локальной машине.

Идея состояла бы в том, чтобы определить некоторые пользовательские COM-интерфейсы, реализующие какой-либо пользовательский протокол связи, а затем иметь серверную программу и клиентскую программу (каждая в своем собственном процессе, работающем на одной и той же локальной машине) и использовать COM для связи между ними. (например, клиент делает запросы к серверу, а сервер возвращает правильные ответы, все с использованием COM-интерфейсов).

Так, например: существуют ли предопределенные COM-интерфейсы для реализации межпроцессного взаимодействия? Если да, то какие?

Было бы полезно иметь какой-нибудь учебник или более подробное руководство по этому вопросу.


person Mr.C64    schedule 19.01.2015    source источник
comment
Поддержка взаимодействия процессов — это врожденная способность COM, она не требует специальных интерфейсов. Мы не размещаем здесь обучающие ссылки, но вы уже это знаете.   -  person Hans Passant    schedule 19.01.2015
comment
Я знаю внутрипроцессные COM-библиотеки DLL (например, расширения оболочки), но я никогда не создавал внепроцессный COM-сервер и никогда не использовал COM как форму межпроцессного взаимодействия. . Ответ @patthoyts является, по крайней мере, начальным руководством, в котором упоминается этот элемент Running Object Table. COM огромен, и наличие некоторых указателей на специализированную документацию и учебники действительно полезно.   -  person Mr.C64    schedule 19.01.2015


Ответы (1)


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

Однако есть много вещей, которые могут пойти не так, особенно с обеспечением правильной маршаллинга ваших интерфейсов. Маршалинг часто плохо тестируется до тех пор, пока вы не начнете использовать несколько процессов или пока не начнете использовать .Net со своими COM-интерфейсами. Использование oleautomation типы и пометка интерфейса в IDL с помощью атрибута [oleautomation] может помочь обеспечить работу сортировки библиотеки типов, но также важно обратить внимание на другие атрибуты, используемые с массивами. Мы обнаружили это в интерфейсе IPPropertyBag2. много лет назад. Описание IDL Visual Studio 6 выглядит следующим образом в ocidl.idl:

HRESULT Read(
            [in] ULONG cProperties,
            [in] PROPBAG2 * pPropBag,
            [in] IErrorLog * pErrLog,
            [out] VARIANT * pvarValue,
            [out] HRESULT * phrError
        );

и не упорядочивает более одного VARIANT из предоставленного массива. Более новая версия выглядит так:

HRESULT Read(
           [in] ULONG cProperties,
           [in, size_is(cProperties)] PROPBAG2 * pPropBag,
           [in, unique] IErrorLog * pErrLog,
           [out, size_is(cProperties)] VARIANT * pvarValue,
           [in, out, unique, size_is(cProperties)] HRESULT * phrError
       );

который правильно связывает размер массива pvarValue с размером, указанным параметром cProperties. Предполагая, что библиотека типов со вторым определением была зарегистрирована, этот интерфейс должен правильно маршалировать сейчас, но несколько лет назад эти отсутствующие параметры стоили нам нескольких клеток мозга, выясняя, почему постоянство терпит неудачу.

person patthoyts    schedule 19.01.2015
comment
Спасибо за эти указатели на таблицу запущенных объектов и за другую общую информацию. Не могли бы вы рассказать немного о том, что маршалинг интерфейса происходит неправильно? Я имею в виду: конечно, у меня не было бы классов STL, таких как std::vector, на границах интерфейса, но был бы я в безопасности, если бы я ограничил типы в упорядоченных интерфейсах простыми типами, такими как целые числа, логические значения и типы COM, такие как BSTR и другие указатели интерфейса (например, IUnknown*)? - person Mr.C64; 19.01.2015
comment
Я подробно рассказал о некоторых подводных камнях, с которыми приходилось сталкиваться в прошлом. - person patthoyts; 19.01.2015
comment
Спасибо за дополнение. - person Mr.C64; 20.01.2015
comment
Позвольте мне только предупредить вас, что второе определение ничего не стоит с точки зрения библиотек типов, поскольку они не описывают длину параметра массива. Для массивов автоматизации вы должны использовать SAFEARRAY или VARIANT, указывающий на единицу. Второе определение будет работать, если вы используете midl.exe для создания кода прокси-заглушки для включения в DLL (DLL компонента или отдельная DLL) и для регистрации для интерфейса в HKEY_CLASSES_ROOT\Interface. - person acelent; 20.01.2015
comment
Действительно, проверка с помощью oleview интерфейса IPropertyBag2 использует пользовательский класс, предоставляемый oleaut32, и не использует маршаллинг библиотеки типов. - person patthoyts; 20.01.2015
comment
Спасибо @PauloMadeira и patthoyts за ваши дополнительные комментарии с подробностями. У вас, ребята, есть ссылки на учебные пособия или другую документацию, которую я могу прочитать, чтобы лучше понять это применение COM для межпроцессного взаимодействия? Спасибо. FWIW, я нашел учебник из 7 шагов по CodeProject, но я думаю, что это, вероятно, слишком много для моих нужд, так как меня интересуют только процессы, работающие на одной и той же локальной машине. Хотя некоторые интерфейсы вроде IConnectionPoint и т.п., обсуждаемые там, могут быть применимы и к моему случаю... - person Mr.C64; 20.01.2015
comment
Это то, что вы должны сделать до шага 6, если вы используете ATL или хотите, и у вас уже есть приложение. Поскольку вас не интересует удаленный доступ к машине, вы можете 1) зарегистрировать сервер с помощью LocalServer32 и заставить его вызывать CoRegisterClassObject и вызывать CoCreateInstance на клиенте, или 2) вызывать RegisterActiveObject на сервере и вызывать GetActiveObject на клиенте, или 3 ) напрямую использовать текущую таблицу объектов (см. GetRunningObjectTable) или 4) реализовать WM_GETOBJECT на сервере и вызвать AccessibleObjectFromWindow на клиенте с помощью OBJID_NATIVEOM... - person acelent; 22.01.2015
comment
И ни один из этих вариантов не является исключительным. Если вы просто хотите увидеть что-то запущенное и работающее, выберите 1, если вам нужен синглтон, выберите 2 или 3 (не дружественный к сценариям), и вам нужно будет убедиться, что приложение работает другими способами (т.е. собственная активация). Вариант 4 может быть полезен, если у вас есть способ выбрать окно, как в Spy++, Process Explorer или Fiddler (⊕). - person acelent; 22.01.2015