Ошибка регистрации COM: ошибка автоматизации: система не может найти указанный файл при установке dll в другую папку, кроме файла tlb

У нас есть компонент COM (назовем его MyLib), разработанный на VB.NET, для использования нашим приложением Access (назовем его MyApp). Для этого нам нужно выполнить регистрацию COM, используя сгенерированные файлы MyLib.dll и MyLib.tlb. Когда я устанавливаю оба файла в папку MyApp, все работает нормально, функция COM вызывается правильно. Однако у меня возникает ошибка, упомянутая в заголовке, когда я устанавливаю dll в общую папку - причина, по которой я это делаю, заключается в том, что мы хотим разрешить установку разных версий MyApp на одном компьютере. Поэтому, если компонент COM не меняется, мы, конечно, хотим поделиться им между этими разными версиями и позволить Windows выполнить подсчет ссылок.

Я не уверен, куда мне поместить файл MyLib.tlb: в установочную папку MyApp или в ту же общую папку, что и MyLib.dll. Но в любом случае я попробовал оба места, и все они дали одну и ту же ошибку. Я попытался сравнить файлы реестра между случаем, когда я помещал MyLib. * В папку MyApp, и случаем, когда я помещал MyLib.dll в общую папку. Я не вижу никакой разницы, кроме, конечно, CodeBase класса, который я пытаюсь зарегистрировать в HKCR \ Wow6432nodes \ CLSID {MYCLSID} \ InprocServer32. Еще я не понимаю, что в обоих случаях нет подключа с именем TypeLib в HKCR \ Wow6432nodes \ CLSID {MYCLSID}, что, как я понимаю, является способом связать TypeLib с dll (но почему он все еще работает когда я помещаю tlb и dll в одну папку?), поскольку в MyApp он знает только то, что есть ссылка, которую мы добавляем по ссылке MyLib.tlb.

Я не понимаю, как именно COM-ссылка работает для приложения Access, поэтому, если я ошибаюсь, поправьте меня. Кто-нибудь может сказать мне, что я сделал не так? Как правильно зарегистрировать общую DLL-библиотеку COM (независимо от того, помещать ли и dll, и tlb в общую папку или нет)? Спасибо!

ОБНОВИТЬ:

Что касается регистрации COM, я использую WIX для создания установщика Windows и heat.exe для сбора информации из файлов dll и tlb. Созданный файл включает информацию о тегах Class, ProgID, TypeLib и Registry. Как я уже упоминал, единственное различие между моими двумя случаями, с точки зрения конфигурации WIX, - это место, куда я помещаю файл MyLib.dll (я предполагаю, что размещение файла MyLib.tlb в папке установки MyApp является правильным способом, снова, пожалуйста, исправьте мой, если я ошибаюсь), и когда я помещаю файлы dll и tlb в папку установки приложения, это работает. Вот некоторая структура реестра после регистрации

Во-первых, у меня есть HKCR \ CLSID \ {MYCLSIDs}, каждый из которых представляет один из моих COM-классов. в подключе "InprocServer32" у меня есть Assembly, Class, CodeBase, RuntimeVersion, threadingModel. А CodeBase - это либо общая папка с файлами (не работает), либо папка установки MyApp (рабочая), то есть разные места, в которые я помещаю dll. Я думал, что будет еще один подключа TypeLib под {MYCLSIDs}, поскольку Access видит только TypeLib, и я думаю, что должна быть какая-то ссылка из TypeLib на фактическую dll, однако в обоих случаях этот подключа отсутствует, но в во втором случае он все еще работает. Есть ли в этом проблема?

Во-вторых, у меня есть HKLM \ Software \ Classes \ CLSID \ {MYCLSIDs}, этот ключ имеет такую ​​же структуру, как описано выше.

В-третьих, HKCR \ {MYPROGIDs}, это просто ProgID моих классов

В-четвертых, HKCR \ Typelib \ {LibID}, который включает информацию из файла tlb, и этот идентификатор взят из GUID сборки проекта компонента COM.

Наконец, HKEY_CLASSES_ROOT \ Interface \ {InterfaceID}, есть подключи с именем ProxyStubClsid32 со значением {00020424-0000-0000-C000-000000000046}, а также с именем TypeLib и значением моего LibID.

Кажется, единственная разница - это CodeBase в первых элементах (я могу ошибаться, но это то, что я вижу). пожалуйста, дайте мне знать, если вы заметите какие-либо проблемы. Спасибо!

ВТОРОЕ ОБНОВЛЕНИЕ:

После установки MyLib.dll в общую папку вызов COM не выполняется. Но если я заменю все значения CodeBase для SHARED_FOLDER \ MyLib.dll на INSTALLDIR \ MyLib.dll и скопирую MyLib.dll в INSTALLDIR, это действительно сработает. И наоборот, после установки MyLib.dll в INSTALLDIR (в этом случае COM работает) я изменяю значения CodeBase с INSTALLDIR \ MyLib.dll на SHARED_FOLDER \ MyLib.dll и делаю копию в SHARED_FOLDER, на этот раз это не удается. Так что, похоже, проблема именно в месте установки, что противоречит моему пониманию COM. И я не думаю, что существует проблема с разрешением для SHARED_FOLDER (я могу ошибаться), поскольку он находится в папке, которую создает мой установщик.


person tete    schedule 26.07.2012    source источник
comment
Вы запускали regsrvr32 для регистрации COM-сервера (и его каталога)?   -  person paulsm4    schedule 26.07.2012
comment
@ paulsm4, спасибо за комментарий. Пожалуйста, посмотрите мое обновление исходного сообщения.   -  person tete    schedule 27.07.2012
comment
Отличный материал - теперь вы знаете, почему домен .net так хорош! Что касается вашего продолжения - мне все еще нечего добавить. ‹< Я полагаю, что размещение файла MyLib.tlb в папке установки MyApp является правильным способом, снова, пожалуйста, исправьте мой, если я ошибаюсь ››. С точки зрения .net размещение .dll в той же папке приложения .net помогает, но с точки зрения Access Accdb / windows расположение папки не имеет никакого значения, поскольку такая регистрация доступна для всех программ Windows, которые могут потребляют объект (ы) com. Таким образом, регистрация windows com отличается от регистрации .net, и расположение папки не имеет значения для Access.   -  person Albert D. Kallal    schedule 27.07.2012
comment
@ AlbertD.Kallal Я добавил второе обновление, пожалуйста. Вы упомянули, что расположение папки не имеет значения, но я получил противоположный результат.   -  person tete    schedule 27.07.2012


Ответы (2)


Я не совсем понимаю, как ссылка на COM работает для приложения Access,

Как объекты com работают для окон, то же самое с тех пор, как они появились в 1990 году. Итак, мы говорим об опоре или технологиях, которые существуют уже 22 года (и это было задолго до того, как объекты создаются в .net).

Таким образом, com работает одинаково в отношении Access, или Delphi, или FoxPro, или VB6, или любой системы, которая может использовать объект com.

Далее важно помнить, что для таких com-объектов реестр таких объектов на компьютере носит ГЛОБАЛЬНЫЙ характер.

Нет НИЧЕГО близкого к концепции динамического связывания объектов, помещенных в ту же папку, что и у вас в .net.

Таким образом, для работы way.net не требуется глобальная регистрация (на самом деле, регистрация не требуется!).

Однако в.net вы МОЖЕТЕ зарегистрировать объект в глобальной сборке, если хотите (GAC). Итак, это выбор, который у вас есть, но это не стандартный объект Windows com, а объект .net. Таким образом, эти объекты.net не имеют НУЛЯ И НИЧЕГО общего со стандартными объектами windows com, которые у нас были уже 22 года.

Таким образом, большинство объектов в .net на самом деле являются локальными для каталога, но это не выбор для стандартных объектов window com.

Итак, чтобы правильно преобразовать объект .net или сборку в пригодный для использования и работающий объект Windows com, этот объект должен быть зарегистрирован на компьютере GLOBAL. Это означает, что вы не используете regsvr32, но на самом деле собираетесь использовать инструмент регистрации .net под названием regasm (который, по сути, действительно выполняет regsvr32 в конечном итоге для вас после создания для вас моста com-объектов). Также имейте в виду, что здесь вам нужно скомпилировать правильную битовую версию.

А если вы выполняете развертывание на других компьютерах, настройте свой проект на создание объекта 2.0, чтобы у вас была большая вероятность того, что библиотеки .net были установлены на целевом компьютере. Итак, во время развертывания вы должны использовать regasm:

Этот: C: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727 \ RegAsm.exe

САМОЕ ВАЖНОЕ: НЕ забудьте добавить / codebase к использованию regasm.exe в командной строке, поскольку вы ДОЛЖНЫ зарегистрировать объект .net в GAC (глобальном кэше сборок). Если вы этого не сделаете, то приложения, отличные от .net, которые поддерживают объекты windows com, не увидят, что noir сможет использовать сборку как стандартный объект windows com.

Поэтому, когда речь идет об объектах, отличных от .net, нет концепции регистрации ActiveX или того, что обычно называют объектом Windows com в папке по основам папок - это всегда глобальный характер.

Таким образом, это спорный вопрос, в какой каталог или папку вы помещаете .dll. После того, как вы правильно зарегистрируете эту .dll, она станет доступной для всех систем, поддерживающих com-объекты.

Это также означает, что во время процесса регистрации в .net вы должны использовать параметр глобального реестра сборок (иначе это не сработает).

person Albert D. Kallal    schedule 27.07.2012
comment
Спасибо, Альберт. С практической точки зрения, видите ли вы какие-либо проблемы в моем описании структуры реестра после регистрации? Я добавил несколько обновлений в исходный пост. - person tete; 27.07.2012
comment
Этот ответ игнорирует возможности параллельного развертывания Windows (SXS), которые позволяют использовать COM-библиотеки DLL без глобальной регистрации. Это все еще не делает его полностью эквивалентным тому, как работает развертывание .NET, но это был большой шаг, когда он был представлен. - person StayOnTarget; 20.07.2017

Оказалось, что MyLib.dll использует некоторые другие библиотеки, которые все еще находятся в папке установки MyApp. Таким образом, в том случае, если MyLib.dll установлен в общей папке, он пытается найти эти библиотеки в тех же библиотеках, что, конечно же, терпит неудачу. Когда я устанавливаю эти библиотеки в общую папку, они работают.

Кстати, я нашел fulogvw.exe очень полезным при отслеживании проблемы с загрузкой сборки. Например, в моем случае в неудачном журнале говорится, что невозможно загрузить файл xxx.dll в SHARED_FOLDER, xxx.dll - это некоторая библиотека, которую использует MyLib.dll, и я понятия не имел, что MyLib.dll она нужна, пока я не увижу журнал.

person tete    schedule 01.08.2012