C#包装器接口错误:E_NOINTERFACE

时间:2009-06-01 17:09:13

标签: c# com rcw

我正在尝试为我拥有的COM对象(名为SC_COM.dll)生成一个C#包装器,但是在将它与Visual Studio 2008(运行Vista)连接时遇到了一些问题。我需要使用COM DLL免费注册 - 我使用清单文件让Visual Studio了解SC_COM.dll,这似乎正在运行。我使用TblImp.exe生成我在Visual Studio 2008中引用的类型库(SC_COMtlb.dll),因此我可以使用我需要的DLL进行早期绑定。这些DLL与清单和可执行文件位于同一目录中。

问题在于:当我实例化对象并尝试在C#中调用其中一个方法时,它会抛出以下错误:

  

检测到错误:无法将“SC_COMtlb.SCAccessObjClass”类型的COM对象强制转换为接口类型“SC_COMtlb.ISCUploader”。此操作失败,因为对于具有IID“{C677308A-AC0F-427D-889A-47E5DC990138}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE))

我不完全确定这个错误意味着什么 - 我已经对错误代码进行了搜索,而且它似乎是一个相对普遍的C#错误。所以我要在这里以错误的方式链接COM对象,还是有一些其他重要的步骤我可能会丢失?

我应该注意到,我不完全确定我生成的类型库(S \ C_COMtlb.dll)如何知道实际的COM DLL在哪里,因为它没有在系统中注册 - 我认为它只是看起来在同一目录中。这可能是问题,如果是这样,我怎样才能更好地联系这两个?

3 个答案:

答案 0 :(得分:6)

尝试将此添加到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}" />

可以从Visual Studio生成的Native.Namespace.Assembly.Name.manifest中找到TLBID,如下所示:

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

我很长时间以来一直在反对这个问题,但是我找到了这些有用的参考资料并将它拼凑在一起并且它对我有用:

答案 1 :(得分:1)

错误代码意味着Visual Studio 认为某个对象应该实现某个接口,但是当我尝试“连接”到该接口时,该对象会响应它不知道关于它。

我猜这个问题出在SC_COM.dll中。 TLBIMP.EXE从存储在DLL中的元数据中提取类和接口信息,并为该类构建包装器。

例如,如果SC_COM是用C ++编写的,如果DLL的创建者在IDL文件中指示某个类实现了该接口,但实际代码不支持该接口,则可能会发生这种情况。

这是此DLL可能存在的另一个常见问题来源:有时您有一个实现ISomething2接口的类,该接口派生自ISomething接口,但类实现只能识别ISomething2。如果实现派生接口,则还必须识别其基接口。这是一个常见的错误。

你有(并控制)DLL的源代码吗?

答案 2 :(得分:0)

哪个版本的Windows?自Windows Vista起,内部清单会覆盖外部清单。默认情况下,C#可执行文件具有内部清单,这意味着您的whatever.exe.manifest文件将被忽略。

如果您转到C#EXE的属性页面,您会在“应用程序”选项卡上看到“图标和清单”部分。将“Manifest”设置为清单文件的名称,它将被嵌入而不是默认文件。

如果这不起作用,您可能必须使用MT.EXE执行一些构建后步骤,以便将外部清单与默认内部清单合并,并将合并后的清单放回到.EXE文件中。 / p>