【问题标题】:C# wrapper interface error: E_NOINTERFACEC# 包装器接口错误:E_NOINTERFACE
【发布时间】:2010-10-30 11:07:05
【问题描述】:

我正在尝试为我拥有的 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 在哪里的,因为它没有在系统中注册——我假设它只是看起来在同一目录中。这可能是问题所在吗?如果是,我怎样才能更好地将两者联系起来?

【问题讨论】:

  • > "...我不完全确定类型库如何...知道实际的 COM DLL 在哪里,因为它没有在系统中注册。" -- 这就是清单的来源。由于代码在出错之前已经达到了它所能达到的程度,我认为它可以很好地找到 COM DLL。如果您仍然不确定,请使用“模块”窗口来验证 COM DLL 是否被列为已加载。

标签: c# com rcw


【解决方案1】:

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

我为此纠结了很长时间,但我找到了这些有用的参考资料并将其拼凑在一起,它对我有用:

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

    • 我在这里使用 Vista。正确的清单似乎是在 Applications-> Icon and Manifest 下设置的。对于您提到的构建后步骤,您是否有任何建议/任何其他链接可供参考?谢谢:-)
    【解决方案3】:

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

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

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

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

    您是否拥有(并控制)该 DLL 的源代码?

    【讨论】:

      猜你喜欢
      • 2012-07-13
      • 1970-01-01
      • 2014-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-05
      相关资源
      最近更新 更多