Зарегистрируйте 32-битный COM-сервер (и сгенерируйте TLB) для использования с 32-битными и 64-битными клиентами

Метод 1. Целевая платформа x86

У меня есть библиотека классов .NET, предназначенная для использования как с 32-разрядными, так и с 64-разрядными клиентами, некоторые из которых являются проектами .NET, а некоторые - проектами C ++ MFC. Я могу заставить библиотеку работать с 32-битными клиентами, но 64-битные клиенты получают исключение «Класс не зарегистрирован». Ковыряться в реестре вроде ставится только ключ win32 (HKEY_CLASSES_ROOT \ Wow6432Node \ TypeLib {GUID} \ 1.0 \ 0 \ win32).

Некоторые примечания к некоторым моим настройкам:

  • Проверяется "Зарегистрироваться для COM-взаимодействия".
  • Установлен флажок "Сделать сборку COM-видимой".
  • «Целевая платформа» - x86.
  • Библиотека содержит 32-битную неуправляемую DLL, которая загружает методы с DLLImport.
  • Клиенты C ++ MFC используют #import "MyLibrary.tlb" для маршалинга кода взаимодействия.
  • Я не вносил никаких изменений в код для поддержки COM. (Например, я не переопределил System.Configuration.Install.Installer.Install.)

Пытаясь решить эту проблему, я попробовал несколько вещей, основанных на некоторых исследованиях и исследованиях.

Способ 2. Целевая платформа "Любой ЦП"

Сначала я попытался установить для целевой платформы значение «Любой процессор». В этом случае ключи win32 и win64 задаются в реестре, и 64-разрядный клиент может взаимодействовать с COM-сервером. Однако при этом я получаю сообщение об ошибке «Была предпринята попытка загрузить программу с неправильным форматом». Это связано с 32-битной неуправляемой библиотекой DLL, которая требует, чтобы я собирал проект с x86.

Метод 3. Получите 64-разрядную сборку неуправляемой зависимости DLL моей библиотеки

Чтобы обойти это, я потенциально мог бы получить 64-битную сборку неуправляемой DLL. Однако мы приобрели эту DLL у третьей стороны, и по какой-то причине они взимают большую дополнительную плату за 64-битную сборку DLL. Помимо явной стоимости, мне также пришлось бы реализовать вызовы DLLImport для каждого и вызвать в зависимости от того, 32-разрядный он или 64-разрядный, что утроит количество методов в моем классе-оболочке. Таким образом, хотя это возможное решение, оно далеко не желательно, и из того, что я понимаю в отношении COM, в этом не должно быть необходимости.

Метод 4: regsvr32.exe

Наиболее распространенное решение, которое я нахожу в Интернете, - это использовать regsvr32.exe для ручной регистрации приложения как для 32-разрядного, так и для 64-разрядного взаимодействия. Однако мне нужен файл TLB для взаимодействия с моими клиентами MFC и очевидно, что regsvr32 не поддерживает это.

Метод 5: regasm.exe

Чтобы получить файл TLB и, надеюсь, зарегистрироваться как для 32-разрядного, так и для 64-разрядного взаимодействия, я также попытался использовать regasm.exe для регистрации сборки вручную. Для этого я использовал следующую команду.

"%WINDIR%\Microsoft.NET\Framework64\v4.0.30319\regasm.exe" "D:\Path\To\MyLibrary.dll" /tlb /nologo

Однако при этом регистрируется только 64-разрядный COM-сервер, а раздел реестра Win32 COM отсутствует. Теперь мой 32-битный клиент не может найти COM-сервер и говорит: «Класс не зарегистрирован». Более того, для 64-битного клиента я получаю ту же ошибку, что и при выборе «Any CPU»: «Была сделана попытка загрузить программу с неправильным форматом».


TL; DR Как зарегистрировать 32-разрядный COM-сервер для использования как с 32-разрядными, так и с 64-разрядными клиентскими приложениями? (Отметив, что мне нужен файл TLB и что серверу необходимо загрузить неуправляемую 32-разрядную DLL.)


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

введите описание изображения здесь

Как видите, мне нужен 64-битный код для взаимодействия с 32-битным кодом через COM-сервер, который, как отмечает @ MC-ND, должен работать. Как мне настроить мой COM-сервер для поддержки этого?


person Logical Fallacy    schedule 21.04.2014    source источник
comment
Обратите внимание на Framework64 в пути Regasm.exe, который вы использовали. Это означает, что вы использовали 64-битную версию, она записывает только те ключи, которые видны 64-битному клиентскому приложению. Вы должны использовать% WINDIR% \ Microsoft.NET \ Framework \ v4.0.30319 \ regasm.exe (нет 64) для записи 32-битных ключей в Wow6432Node. Нет никакого волшебного решения для попытки загрузить 32-битный неуправляемый код в 64-битный процесс, это просто невозможно. Также не было бы большого смысла в том, чтобы ваш поставщик разрабатывал 64-битную версию, если бы это, конечно, могло работать. Инженеры-программисты не могут жить только на солнце и воздухе.   -  person Hans Passant    schedule 22.04.2014
comment
@HansPassant, я включил диаграмму; проясняет ли это то, что я пытаюсь достичь? Насколько я понимаю, COM-серверы позволяют 64-битному коду взаимодействовать с 32-битным кодом. См. ссылку, предоставленную MD ND. Это то, чего я пытаюсь достичь с помощью своего COM-сервера.   -  person Logical Fallacy    schedule 22.04.2014
comment
проверьте это   -  person Mert Gülsoy    schedule 10.08.2016


Ответы (1)


Из MSDN: взаимодействие процессов

В 64-битной Windows 64-битный процесс не может загрузить 32-битную библиотеку динамической компоновки (DLL). Кроме того, 32-разрядный процесс не может загрузить 64-разрядную DLL.

Ваш лучший вариант, кажется, скомпилировать ваш компонент как 32-битный внепроцессный COM-сервер.

person MC ND    schedule 22.04.2014
comment
Я использую COM-сервер. Есть идеи, что я делаю не так, что он не работает так, как должен? - person Logical Fallacy; 22.04.2014
comment
@DavidEnglund, я думаю, может быть, мы двое не о том же. Вы используете вне процесса, .EXE, COM-сервер? - person MC ND; 22.04.2014
comment
Обновление: я разработал внепроцессный COM-сервер для проверки концепции, который работает для всех 4-х клиентских конфигураций (32-разрядных / 64-разрядных, управляемых / неуправляемых), которые у меня есть. Для поддержки неуправляемых клиентов я изменил пример CSExeCOMServer для вывода файла TLB с помощью сообщения событие сборки и regasm. - person Logical Fallacy; 23.04.2014
comment
Ответ на этот вопрос по-прежнему заключается в том, что необходим 32-битный внепроцессный COM-сервер, поэтому я приму его. Однако после 3 дней попыток мне не удалось заставить это работать с системным суррогатом по умолчанию, dllhost.exe, и мне нужно двигаться дальше. Хотел бы я написать ответ с реальным решением, но, к сожалению, у меня его нет. См. Мой предыдущий комментарий для примера кода, который почти привел меня туда. - person Logical Fallacy; 25.04.2014
comment
@DavidEnglund, извините, кажется, я недостаточно ясно объяснил. Ваша единственная реальная проблема заключается в том, что у вас есть 32-битная DLL, и она может быть загружена только 32-битным процессом. Вы можете построить что угодно вокруг этого, сохранив свой доказательный сервер, чтобы предоставить требуемый интерфейс для остального мира, но в соответствии с ним 32-битный процесс является обязательным, пока используется 32-битная dll. - person MC ND; 25.04.2014