为什么我不能将我的 COM 对象转换为它在 C# 中实现的接口? [英] Why cannot I cast my COM object to the interface it implements in C#?

查看:14
本文介绍了为什么我不能将我的 COM 对象转换为它在 C# 中实现的接口?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 dll 中有这个接口(这个代码显示在 Visual Studio 中的元数据中):

I have this interface in the dll (this code is shown in Visual Studio from metadata):

#region Assembly XCapture.dll, v2.0.50727
// d:svndashboard	runkSourceMockDiagnosticsServerlibXCapture.dll
#endregion

using System;
using System.Runtime.InteropServices;

namespace XCapture
{
    [TypeLibType(4160)]
    [Guid("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX")]
    public interface IDiagnostics
    {
        [DispId(1)]
        void GetStatusInfo(int index, ref object data);
    }
}

所以我用这样的类创建了一个 COM 服务器:

So I created a COM server with such class:

[ComVisible(true)]
[Guid(SimpleDiagnosticsMock.CLSID)]
[ComDefaultInterface(typeof(IDiagnostics))]
[ClassInterface(ClassInterfaceType.None)]
public class SimpleDiagnosticsMock : ReferenceCountedObject, IDiagnostics
{
    public const string CLSID = "281C897B-A81F-4C61-8472-79B61B99A6BC";

    // These routines perform the additional COM registration needed by 
    // the service. ---- stripped from example

    void IDiagnostics.GetStatusInfo(int index, ref object data)
    {
        Log.Info("GetStatusInfo called with index={0}, data={1}", index, data);

        data = index.ToString();
    }
}

服务器似乎工作正常,我可以使用 VBScript 中的对象.但后来我尝试从另一个 C# 客户端使用它:

Server seems to work fine, and I am able to use the object from a VBScript. But then I try to use it from another C# client:

    [STAThread]
    static void Main(string[] args)
    {
        Guid mockClsId = new Guid("281C897B-A81F-4C61-8472-79B61B99A6BC");
        Type mockType = Type.GetTypeFromCLSID(mockClsId, true);
        IDiagnostics mock = (IDiagnostics)Activator.CreateInstance(mockType);

        //var diag = mock as IDiagnostics;

        object s = null;
        mock.GetStatusInfo(3, ref s);

        Console.WriteLine(s);
        Console.ReadKey();
    }

它失败了

无法将System.__ComObject"类型的 COM 对象转换为接口键入XCapture.IDiagnostics".此操作失败,因为对具有 IID 的接口的 COM 组件上的 QueryInterface 调用'{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}' 失败,原因如下错误:不支持此类接口(HRESULT 异常:0x80004002(E_NOINTERFACE)).

Unable to cast COM object of type 'System.__ComObject' to interface type 'XCapture.IDiagnostics'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

我做错了什么?

我也尝试过使用 InvokeMember,除了我无法获得 ref-returned data 参数之外,这有点工作.

I have also tried to use InvokeMember, and that kinda worked except that I wasn't able to get the ref-returned data parameter.

将 STAThread 属性添加到我的 Main 过程中.这并不能解决问题,但您真的应该将 STAThread 与 COM 结合使用,除非您绝对确定不需要它.请参阅下面 Hans Passant 的回答.

added STAThread attribute to my Main procedure. This does not solve the issue, but you really should use STAThread with COM unless you're absolutely sure you don't need it. See Hans Passant's answer below.

推荐答案

所以,问题是我的带有 IDiagnostics 接口的 DLL 是从 TLB 生成的,而 TLB 从未注册过.

So, the problem was that my DLL with IDiagnostics interface was generated from a TLB, and that TLB never got registered.

由于 DLL 是从 TLB 导入的,RegAsm.exe 拒绝注册该库.所以我使用regtlibv12.exe工具来注册TLB本身:

Since the DLL was imported from the TLB, RegAsm.exe refuses to register the library. So I used the regtlibv12.exe tool to register the TLB itself:

C:WindowsMicrosoft.NETFrameworkv4.0.30319
egtlibv12.exe "$(ProjectDir)libDiagnostics.tlb"

然后一切都神奇地开始工作了.

Then everything magically started to work.

由于 regtlibv12 不是受支持的工具,我仍然不知道如何正确执行此操作.

Since regtlibv12 is not a supported tool, I still don't know how to do this properly.

这篇关于为什么我不能将我的 COM 对象转换为它在 C# 中实现的接口?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆