CLSIDFromProgID выполнен успешно, но CreateInstace не работает! Почему?

Я пытаюсь создать экземпляр COM-объекта. У меня есть имя класса, реализующего интерфейс, и я получаю CLSID с помощью CLSIDFromProgID(). Так как я получаю CLSID, я думал, что теперь все должно быть хорошо. Однако, когда я вызываю CreateInstance и передаю CLSID, я получаю сообщение об ошибке «Класс не зарегистрирован». Также я получаю эту ошибку только на некоторых компьютерах. Он работает без ошибок на нескольких компьютерах. Я не понимаю, где может быть проблема. Мой реестр грязный? Кто-нибудь знает, что здесь происходит? Спасибо за вашу помощь!

Я просто хочу добавить, что это класс .NET COM. Соответствующие записи находятся в реестре, а DLL — в GAC.


person Juba    schedule 03.11.2008    source источник


Ответы (4)


Это двухэтапный процесс в реестре. Вы использовали ProgID для получения CLSID. Затем, когда вы вызываете CreateInstance, COM использует CLSID для поиска пути к dll. Вы можете использовать regedit самостоятельно, чтобы найти CLSID и посмотреть, как выглядит эта запись.

person Corey Trager    schedule 03.11.2008
comment
Допустим, это класс .net COM. Тогда куда он смотрит, когда я вызываю CreateInstance()? - person Juba; 04.11.2008
comment
По-моему, без разницы. КОМ есть КОМ. Реестр сопоставляет CLSID с путями к DLL. - person Corey Trager; 04.11.2008

CLSIDFromProgId просто ищет имя ProgId в реестре и преобразовывает его в CLSID, ему не нужно смотреть ни на что за пределами реестра или даже проверять, действительно ли что-то реализует этот CLSID.

Когда вы вызываете CreateInstance для CLSID, Windows будет искать в реестре, как должен быть создан экземпляр объекта (обычно exe или dll). Затем он попытается загрузить dll (или запустить exe) и создать из нее объект.

В MSDN есть много документации по задействованным процессам, например, см. "Объекты класса COM и CLSID", и если вы много работаете с COM, стоит изучить процесс от первых руководителей, так как это может сэкономить много времени и хлопот при отладке этого типа проблемы.

person Rob Walker    schedule 03.11.2008
comment
Допустим, это класс .net COM. Тогда куда он смотрит, когда я вызываю CreateInstance()? - person Juba; 04.11.2008
comment
Посмотрите в HKEY_CLASSES_ROOT\CLSID\{..your clsid..}\ Вы должны увидеть подраздел Server32 или InprocServer23, который сообщит вам, какой исполняемый файл зарегистрирован для обработки объекта. Инструмент oleview полезен для диагностики этих проблем... откройте командную строку Visual Studio и введите: oleview - person Rob Walker; 04.11.2008

Спасибо за ваши ответы. Сборки .Net были правильно зарегистрированы и присутствовали в GAC. Одним из приложений, которое полностью подтвердило это, был Process Explorer. Вы можете просмотреть библиотеки DLL, загружаемые каждым приложением. Итак, отсюда я смог увидеть, действительно ли приложение, которое создавало экземпляры COM-объектов, могло загружать библиотеки DLL или нет. Я узнал, что это действительно происходит. Проблема была из-за разных региональных настроек. Мы обнаружили, что приложение выдавало исключение, когда в качестве региона не был указан США. Эта проблема была исправлена. Сообщение об ошибке «Класс не зарегистрирован» не очень помогло. К счастью, это было быстрое решение.

person Juba    schedule 05.11.2008

Используя в качестве примера shell32, вы можете создать новый экземпляр таким образом;

var shl = (Shell) Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));

Это потребует ссылки на существующий компонент;

var shl2 = (Shell) Marshal.GetActiveObject("Shell.Application");

Вот ссылка на то, как сделать то же самое в IronPython.

** Обратите внимание, что здесь использовался progid, clsid был бы почти идентичен, просто используйте Type.GetTypeFromCLSID({GUID}).

person RandomNickName42    schedule 16.11.2009