【问题标题】:How to verify that C#/.NET COM object is actually a COM object?如何验证 C#/.NET COM 对象实际上是 COM 对象?
【发布时间】:2019-11-10 00:23:58
【问题描述】:

我有一个 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 );
    }
}

实际的入口点在类 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 创建的。

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

注册表显示一个具有正确名称的条目,并且类 ID 设置为正确的 guid。但是,我还是想加载它并通过 COM 接口运行它。

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

【问题讨论】:

    标签: c# com


    【解决方案1】:

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

    因此,如果您的类是这样定义的(我个人不使用.NET 的 COM 接口,但如果接口是双重的,则不会改变),请注意我添加了一个好的 COM 实践的 progid:

    [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 位宽)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-07-19
      • 1970-01-01
      • 2012-10-02
      • 2011-03-05
      • 2013-02-02
      • 2010-12-07
      • 2018-10-14
      相关资源
      最近更新 更多