如何将一个COM类实例作为参数传递给C#中的另一个COM方法

本文关键字:COM 参数传递 方法 另一个 一个 实例 | 更新日期: 2023-09-27 18:22:20

我使用TlbImp.exe为2个COM DLL创建了一个包装器。其中一个类被包装器描述为

using System;
using System.Runtime.InteropServices;
namespace GNOTDRSIGNATURESERVERLib
{
    [CoClass(typeof(GNOTDRSignatureServerClass)),
        Guid("20CBF9E0-06BF-11D3-97B5-0080C878CFFA")]
    public interface GNOTDRSignatureServer
    {
    }
}

此对象必须作为参数传递

using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace GN8000Lib
{
    [TypeLibType(2),
         ClassInterface(0), 
         ComSourceInterfaces("GN8000Lib._I8000Events'0"),
         Guid("DCAD84FE-43A8-11D3-B1A2-005004131886")]
    public class GN8000Class : I8000
    {
        [MethodImpl(MethodImplOptions.InternalCall)]
        public extern GN8000Class();
        [DispId(6)]
        [MethodImpl(MethodImplOptions.InternalCall)]
        void I8000.Initialize(
            [IUnknownConstant] [MarshalAs(UnmanagedType.IUnknown)] [In]
            object pSigServer = null);
    }
}

然后我调用这样的方法:

var gn8000 = new GN8000();
var signatureServer = new GNOTDRSignatureServer();
gn8000.Initialize(signatureServer);

我认为正在传递的对象不是正确的对象。我觉得TlbImp.exe可以链接这些DLL并使用GNOTDRSignatureServer而不是UnmanagedType.IUnknown,或者我可以使用System.Runtime.InteropServices.Marshal.GetComInterfaceForObject

我的代码出了什么问题?

如何将一个COM类实例作为参数传递给C#中的另一个COM方法

声明看起来很难看,我假设它们是由某种反向工程工具生成的,而您不是自己编写的。在这种情况下,有一个空接口并不罕见。COM中的等效接口是dispinterface,该接口仅支持通过IDispatch进行后期绑定。这是很常见的,COM服务器可能被设计为使用脚本语言,即只支持后期绑定的运行时环境。与.NET中的ComInterfaceType.InterfaceIsIDispatch相同。[DispId]对于后期绑定很重要,请按编号而不是名称调用。

这也使得论点类型易于解释。脚本语言使用VARIANT作为变量类型。与您在C#代码中声明为对象的变量非常相似,它可以存储任何值。功能,而不是bug。