5

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

4

3 回答 3

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" />

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

于 2009-06-29T15:38:41.460 回答
1

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

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

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

于 2009-06-01T17:56:50.207 回答
1

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

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

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

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

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

于 2009-06-01T18:59:42.917 回答