如何验证C#/.NET COM 对象实际上是一个COM 对象?

How to verify that C#/.NET COM object is actually a COM object?

我有一个 C# 项目,它创建了一个用于 POS 终端的 COM 对象。在我将它提供给客户之前,我想确保它可以作为 COM dll 工作。 RegAsm 说它有效。

using System;
using System.Runtime.InteropServices;

namespace POS
{
    [Guid( "0135bc5c-b248-444c-94b9-b0b4577f5a1a" )]
    [InterfaceType( ComInterfaceType.InterfaceIsDual )]
    [ComVisible( true )]
    public interface ITwoWay
    {
        // The Initialize method is called to establish the communications connection...
        [DispId( 1 )]
        void Initialize( String IPAddress, long Port, long MaxPacketSize );

        // A convenience method that allows the POS to test the Third Party’s back-end...
        [DispId( 2 )]
        void TestConnect();

        // The Terminate method is called to indicate that the POS system is about to terminate...
        [DispId( 3 )]
        void Terminate();

        // All interface calls made during a transaction send the same record format with specific reply fields ...
        [DispId( 4 )]
        void TransactionCall( String viPOSMsg, ref String InterceptArray );
    }
}

实际入口点在class TwoWay

中定义
using System.Runtime.InteropServices;
using System.EnterpriseServices;

namespace POS
{
    [Guid( "0135bc5c-b248-444c-94b9-b0b4577f5a1b" )]
    [ComDefaultInterface(typeof(ITwoWay))]
    [ClassInterface( ClassInterfaceType.None )]
    [ComVisible( true )]
    public class TwoWay : ITwoWay
    ...
    [ComVisible( true )]
    public void Initialize( string iPAddress, long port, long maxPacketSize )
    ...

我原以为我可以将 .tlb 导入另一个 .net 项目并以这种方式对其进行测试,但是当我将我的 COM 项目添加为 COM 引用时,VS 拒绝了它,因为它是作为 .NET dll 创建的。

我试图为 运行 CreateObject 创建一个 vb 脚本,但是权限错误。我试图设置 I_USER 帐户等,但无法进行。

注册表显示了一个名称正确的条目,并且 class id 设置为正确的 guid。但是,我仍然想通过 COM 接口加载它并运行它。

如何验证 COM .dll 实际上是 COM .dll?这么老了,一定有办法的。

一种快速的方法是使用 .NET 的 dynamic 功能,这对 COM 编程非常有用

所以如果你 class 是这样定义的(我个人不使用 .NET 的 COM 接口,但如果接口是双重的,那不会改变任何东西),请注意我添加了一个 progid,它是良好的 COM 实践:

[Guid("0135bc5c-b248-444c-94b9-b0b4577f5a1a")]
[ProgId("MyComponent.TwoWay")]
[ComVisible(true)]
public class TwoWay
{
    public void Initialize(string IPAddress, long Port, long MaxPacketSize)
    {
        Console.WriteLine(IPAddress);
    }

    // other methods...
}

然后我可以像这样使用 .NET 对其进行测试(无需创建 TLB,只需使用 regasm 注册它):

var type = Type.GetTypeFromProgID("MyComponent.TwoWay");
dynamic twoway = Activator.CreateInstance(type);

twoway.Initialize("hello", 0, 0);

不方便的是你没有自动完成,你只需要注意传递适合的参数。 .NET 足够聪明,可以将 Int32 转换为 Int64(请注意,您使用的 C# long 是 64 位宽)。