Проблема с отменой регистрации COM dll

У меня есть проект, в котором много DLL-библиотек COM, по требованию мне пришлось отменить регистрацию COM-библиотеки DLL, что я сделал, вызвав параметр Regsvr32 -u, и dll не была зарегистрирована.

Эта операция отмены регистрации, похоже, удаляет интерфейс, скажем, ICommon interface, что делает другие COM-объекты непригодными для использования.

Этот ICommon интерфейс реализован всеми другими компонентами COM, в сценарии реестра незарегистрированной библиотеки COM Dll я не вижу кода, который удаляет этот ICommon реестр формы интерфейса, как это удаляется.

Как удаляется информация об интерфейсе для данного CoClass, играют ли BEGIN_COM_MAP и COM_INTERFACE_ENTRY какую-либо роль?


person user2101801    schedule 09.07.2014    source источник
comment
Когда вы просматриваете библиотеку типов, виден ли интерфейс ICommon во всех библиотеках DLL компонентов COM, которые используют ICommon?   -  person Niall    schedule 09.07.2014
comment
У вас может быть этот интерфейс в библиотеках типов 2+ (типичная проблема), а затем отмена регистрации ЛЮБОЙ удаляет регистрацию интерфейса.   -  person Roman R.    schedule 09.07.2014
comment
Если это проблема, быстрое решение может заключаться в перерегистрации любой из оставшихся библиотек с этим интерфейсом. Правильным исправлением было бы устранение дублирования в библиотеках типов.   -  person Roman R.    schedule 09.07.2014
comment
Спасибо, Роман ... сделаю, если это возможно   -  person user2101801    schedule 09.07.2014


Ответы (2)


COM изобилует проблемами DLL Hell. Режим отказа здесь заключается в том, что при удалении сервера также удаляются ключи из HKLM \ Software \ Classes \ Interface. Это сообщает COM, какую реализацию прокси / заглушки следует использовать для маршалинга интерфейса через границы подразделения. Ключ ProxyStubClsId32 для интерфейса идентифицирует прокси.

Это нарушает работу любой клиентской программы, использующей другие COM-серверы, реализующие интерфейс, они больше не могут маршалировать интерфейс, и они умрут во время выполнения с E_NOINTERFACE. Сам по себе сбивающий с толку код ошибки, можно предположить, что интерфейс каким-то образом исчез, но на самом деле он жалуется на то, что COM-объект не реализует IMarshal. Последний вздох, когда COM не может найти ключ в реестре.

Не то чтобы это обычно трудно исправить, вам просто придется перерегистрировать отказавший COM-сервер, он вернет ключ.

Нет реальной защиты от этой потери, вам придется реализовать сложную схему подсчета ссылок, которая записывает, сколько COM-серверов зависит от прокси-сервера и удаляет только ключ (и DLL, если это настраиваемый прокси) когда он обратится к нулю. Это было сделано, однако требуется только один установщик, который не поддерживает схему, или неразумный Regsvr32.exe / u, выполненный из командной строки, как и вы, чтобы он не сработал.

person Hans Passant    schedule 09.07.2014
comment
Все это, конечно, правда, но защита довольно проста - никогда не иметь интерфейса для библиотек типов 2+. Тогда не может быть ситуации, когда одна вещь ушла, а другая вещь все еще использует пропавшую вещь. IDL importlib - это инструмент для ссылки между библиотеками типов. - person Roman R.; 09.07.2014
comment
+1 Я собирался написать это почти дословно. Я никогда не объединяю информацию о прокси-заглушках для интерфейсов, которые являются общими для нескольких PE, именно по этой причине, выбирая библиотеку отдельного типа и, если необходимо, автономный маршаллер (которого я также стараюсь избегать ). - person WhozCraig; 09.07.2014
comment
Это именно та ошибка, которую я вижу ... спасибо, что нашли время, чтобы ответить на этот вопрос - person user2101801; 09.07.2014

Да, эти элементы играют роль, как и библиотека типов, используемая regsvr32.

Если ICommon интерфейс виден при просмотре библиотеки типов COM-компонента, этот тип рассматривается как «принадлежащий» компоненту, и процесс regsvr32 добавляет этот компонент в качестве местоположения этого интерфейса. При удалении действовало наоборот. Таким образом, хотя интерфейс ICommon все еще используется, поскольку компонент, который рассматривается как «владелец» интерфейса, удаляется, регистрация интерфейса также удаляется. Новый «владелец» не устанавливается (или не регистрируется) автоматически, это необходимо сделать путем повторной регистрации подходящего компонента.

Я рекомендую изолировать ICommon интерфейс от одной библиотеки типов (компонент COM) и импортировать эту библиотеку типов везде, где требуется интерфейс, тем самым обеспечивая единого «владельца» интерфейса.

Примечание. на основании опыта работы с унаследованным кодом (с этой проблемой), который мне пришлось исправить, будьте очень осторожны при импорте или попытке повторно объявить системные интерфейсы (например, ISerializable и т. д.), поскольку regsvr32 может удалить также и из реестра; вызывая мир боли. Удаление в этом случае почти разрушило всю систему.

person Niall    schedule 09.07.2014