Ошибка интерфейса оболочки C #: E_NOINTERFACE - PullRequest
3 голосов
/ 01 июня 2009

Я пытаюсь создать оболочку C # для имеющегося у меня COM-объекта (с именем SC_COM.dll), но у меня возникают некоторые проблемы, связанные с Visual Studio 2008 (работает под управлением Vista). Мне нужно сделать это без регистрации в COM DLL - я использую файл манифеста, чтобы Visual Studio узнала о SC_COM.dll, и это, похоже, работает. Я использовал TblImp.exe для создания библиотеки типов (SC_COMtlb.dll), на которую я ссылаюсь в Visual Studio 2008, чтобы я мог выполнить раннее связывание с нужной мне DLL. Библиотеки DLL находятся в одном каталоге с манифестом и исполняемым файлом.

Вот проблема: когда я создаю экземпляр объекта и пытаюсь вызвать один из его методов в C #, он выдает следующую ошибку:

Обнаружена ошибка: невозможно преобразовать COM-объект типа «SC_COMtlb.SCAccessObjClass» в тип интерфейса «SC_COMtlb.ISCUploader». Эта операция завершилась неудачно, поскольку вызов QueryInterface для компонента COM для интерфейса с IID '{C677308A-AC0F-427D-889A-47E5DC990138}' завершился ошибкой из-за следующей ошибки: такой интерфейс не поддерживается (Исключение из HRESULT: 0x80004002 (E_NOINTERFACE)) .

Я не совсем уверен, что означает эта ошибка - я провел поиск по коду ошибки, и, похоже, это относительно общая ошибка C #. Так что я собираюсь связать COM-объект здесь неправильно или есть какой-то другой важный шаг, который я могу пропустить?

Вероятно, я должен отметить, что я не совсем уверен, как созданная мной библиотека типов (S \ C_COMtlb.dll) знает, где на самом деле находится COM DLL, так как она не зарегистрирована в системе - я предполагаю, что она просто выглядит в том же каталоге. Может ли это быть проблемой, и если да, то как мне лучше связать их?

Ответы [ 3 ]

6 голосов
/ 29 июня 2009

Попробуйте добавить это в свой App.exe.manifest:

<comInterfaceExternalProxyStub 
  name="ISCUploader" 
  iid="{C677308A-AC0F-427D-889A-47E5DC990138}"
  proxyStubClsid32="{00020424-0000-0000-C000-000000000046}"
  baseInterface="{00000000-0000-0000-C000-000000000046}"
  tlbid = "{PUT-YOUR-TLB-GUID-HERE}" />

Где TLBID можно найти в сгенерированном Visual Studio Native.Namespace.Assembly.Name.manifest, выглядя так:

<typelib tlbid="{A-GUID-IS-HERE--USE-IT}"
  version="1.0" helpdir="" resourceid="0" flags="HASDISKIMAGE" />

Я довольно долго бился об это, но я нашел эти полезные ссылки и собрал их вместе, и это работает для меня:

1 голос
/ 01 июня 2009

код ошибки означает, что Visual Studio считает , что определенный объект должен реализовывать определенный интерфейс, но когда я пытаюсь «подключиться» к этому интерфейсу, объект отвечает, что он не знает о это.

Я бы предположил, что проблема в SC_COM.dll. TLBIMP.EXE извлекает информацию о классе и интерфейсе из метаданных, хранящихся в DLL, и создает оболочки для этого класса.

Например, если SC_COM написан на C ++, это может произойти, если создатель DLL указал в файле IDL, что класс реализует этот интерфейс, но реальный код не поддерживает этот интерфейс.

Вот еще один распространенный источник проблем, с которыми может столкнуться эта DLL: иногда у вас есть класс, реализующий интерфейс ISomething2, который происходит от интерфейса ISomething, но реализация класса распознает только ISomething2. Если вы реализуете производный интерфейс, вы должны также распознать его базовый интерфейс. Это распространенная ошибка.

Есть ли у вас (и вы контролируете) исходный код для DLL?

0 голосов
/ 01 июня 2009

Какая версия Windows? Начиная с Windows Vista, внутренний манифест переопределяет внешний манифест. По умолчанию исполняемые файлы C # имеют внутренние манифесты, что означает, что ваш файл whatever.exe.manifest будет игнорироваться.

Если вы перейдете на страницу свойств вашего C # EXE, то увидите, что на вкладке «Приложение» есть раздел «Значок и манифест». Установите «Манифест» на имя вашего файла манифеста, и он будет встроен вместо файла по умолчанию.

Если это не сработает, вам может потребоваться выполнить некоторые шаги после сборки с MT.EXE, чтобы объединить ваш внешний манифест с внутренним по умолчанию и поместить объединенный манифест обратно в файл .EXE. 1006 *

...