TL; DR Делать все записи реестра, созданные regsvr32
нужно присутствовать в манифесте SxS reg-free-COM и наоборот?
Я пытаюсь получить бесплатную регистрацию COM для стороннего компонента.
чтение вверх на Я считаю, что в предмете упоминается несколько элементов, которые можно поместить в манифест:
Из документов, мы можем добавить следующие теги в манифест для описания COM-компонента:
assemblyIdentity
— который на самом деле просто описывает «абстрактный сборка«насколько я могу судитьcomClass
— описывает класс COM (интерфейс IID). Казалось бы, это всегда нужно.typelib
— когда?comInterfaceExternalProxyStub
— когда?comInterfaceProxyStub
— когда?Из других документов для HKEY_LOCAL_MACHINE\SOFTWARE\Classes
мы можем заметить, что есть несколько категорий для записей реестра COM:
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{CLSID}
Я предполагаю примерно соответствует comClass
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\{IID}
будет соответствовать или comInterface[External]ProxyStub
, но я серьезно без понятия когда использовать какой (или оба)typelib
явная записьС помощью regsvr42 чтобы извлечь материал, который я пытаюсь освободить DLL дает манифест, который содержит только comClass
записей, нет записей typelib или ProxyStub. (И я перепроверил написанные ключи, DLL, о которой идет речь, pdm.dll
Диспетчер отладки процессов MS записывает только эти ключи, т. Е. В реестре отсутствует информация о библиотеке типов или заглушки прокси.)
Если реестр содержит только информацию, которая относится к comClass
означает ли это, что этой информации будет достаточно в манифесте SxS, или может потребоваться дополнительная информация в манифесте?
Кроме того, я заметил, что реестр содержит VersionIndependentProgId
и ProgId
в конце которого добавлен номер версии. Манифест имеет только ProgId
запись и состояние документов:
ProgID : Зависящий от версии программный идентификатор, связанный с
COM компонент. Формат ProgID — это
<vendor>.<component>.<version>
,
Но документы также утверждают
comClass элемент может иметь
<progid>...</progid>
элементы как
дочерние элементы, в которых перечислены зависимые от версии программы.
а также они говорят что атрибут progid должен быть независимым от версии.
Итак, что здесь поставить? И имеет ли значение, когда клиент не запрашивает конкретную версию?
Элемент assemblyIdentity всегда требуется, часть манифеста сантехника. Вы всегда должны предоставлять элемент comClass, он заменяет HKLM\Software\Classes\CLSID
ключ реестра и используется для работы вызова CoCreateInstance () клиента. Элемент file называет исполняемый файл COM-сервера.
Остальные ключи являются необязательными, они необходимы для работы маршалинга. Маршалинг происходит, когда клиентский вызов должен быть выполнен в другом потоке. Что будет всегда Это происходит, когда сервер и клиент находятся в разных процессах, например, для сервера вне процесса или когда сервер работает на другом компьютере. И это может произойти, когда ThreadingModel, указанный в элементе comClass, требует этого. Другими словами, когда COM-объект был создан в одном потоке, но вызывается в другом, а сервер не является потокобезопасным.
RPC реализует маршалинг, но у него есть одна задача, с которой ему нужна помощь. Необходимо знать, каковы аргументы функции, а также тип возвращаемого значения. Так что он может правильно сериализовать их значения в пакет данных, который может быть передан по сети или передан в код в другом потоке, который выполняет вызов. Это работа прокси. Заглушка работает на принимающей стороне и десериализует аргументы для построения стекового фрейма и выполняет вызов. Возвращаемое значение функции, а также любые значения аргументов, переданные по ссылке, затем возвращаются к вызывающей стороне. В противном случае код, который делает вызов, совершенно не осознает, что не вызывал функцию напрямую.
Есть четыре основных случая:
COM-сервер вообще не поддерживает такой вызов и должен всегда использоваться из того же потока, в котором он был создан. Остановитесь там, не нужно ничего добавлять к манифесту.
COM-сервер реализует IMarshal интерфейс. Автоматически запрашивается COM, когда он не может найти другой способ упорядочить вызов. Это довольно редко, за исключением случая, когда COM-сервер агрегирует маршаллер со свободным потоком. Другими словами, сам по себе полностью поточно-ориентирован, без какой-либо помощи и всегда работает в процессе. ДПМ, скорее всего, будет работать именно так. Остановитесь там, не нужно ничего добавлять к манифесту.
Автор COM-сервера начал свой проект, написав описание интерфейса сервера на языке IDL. Который был тогда скомпилирован MIDL. Один из доступных вариантов — автоматическая генерация кода из объявлений IDL, код, который можно использовать для создания отдельной библиотеки DLL, реализующей прокси и заглушку. IDL достаточно богат, чтобы описать детали типов аргументов функции и их использования, чтобы позволить маршалинг выполнять этим автоматически сгенерированным кодом. Иногда атрибутов IDL недостаточно, автор COM затем пишет пользовательский маршаллер. COM загружает эту DLL во время выполнения для автоматического создания объектов прокси и заглушки.
Специфично для подмножества COM Automation (интерфейс IDispatch), в Windows есть встроенный маршаллер, который знает, как упорядочить вызовы, отвечающие требованиям подмножества. Очень распространенный. Он использует библиотеку типов для обнаружения объявления функции.
Последние две пули требуют использования HKLM\Software\Classes\Interface
, он имеет записи для IID для каждого интерфейса. Вот как COM узнает, как создать прокси и заглушку для интерфейса. Если он не может найти ключ, он возвращается к IMarshal. Вы должны использовать элемент comInterfaceExternalProxyStub для замены раздела реестра. Использование comInterfaceProxyStub является особым случаем, когда прокси-код и заглушка включаются в исполняемый файл COM-сервера, а не в отдельный файл. Например, опция в проектах ATL включена с помощью мастера «Разрешить объединение прокси / заглушки».
В последнем маркере также требуется использование элемента typelib, чтобы встроенный маршаллер мог найти нужную ему библиотеку типов.
ProgId требуется, когда COM-клиент использует позднюю привязку через IDispatch, вспомогательная функция CreateObject () в клиентской библиотеке поддержки времени выполнения является шаблонной. Используется в любом скриптовом хосте, например.
Наличие некоторой внутренней информации о том, как был создан COM-сервер, безусловно, помогает, всегда обращайтесь к поставщику или автору за советом. Однако его можно перепроектировать, посмотрев, какие разделы реестра записываются при регистрации сервера. Инструмент SysInternals ProcMon — лучший способ убедиться в этом. Основные вещи для поиска:
Если вы видите, напишите HKLM\Software\Classes\Interface
ключ, то вы можете предположить, что вы должны предоставить элемент comInterface | External | ProxyStub
Если вы видите его, напишите {00020420-0000-0000-C000-000000000046} для ключа ProxyStubClsid32, тогда вы можете предположить, что он использует стандартный маршаллер, и вы должны использовать элемент comInterfaceExternalProxyStub, а также элемент typelib. Затем вы также должны увидеть, как он записал раздел реестра IID TypeLib, а также запись в разделе реестра HKLM \ Software \ Classes \ Typelib. Последний дает путь к библиотеке типов. Почти всегда так же, как COM-сервер, встраивание библиотеки типов в качестве ресурса очень распространено. Если это отдельный файл (файл .tlb), вы должны его развернуть.
Если значение ключа ProxyStubClsid32 является другим guid, то вы можете предположить, что оно использует свою собственную DLL прокси / заглушки. Затем вы также должны увидеть, как он пишет ключ CLSID для прокси, его ключ InProcServer32 дает вам путь к DLL. Если это имя файла совпадает с именем файла сервера, вы можете предположить, что код прокси / заглушки был объединен, и вместо этого вы должны использовать элемент comInterfaceProxyStub. Если нет, то comInterfaceExternalProxyStub требуется, и вы должны развернуть DLL
Если вы видите это, напишите ProgID в HKLM\Software\Classes
затем используйте элемент progid, в точности как показано на графике.
Других решений пока нет …