C#调用COM接口的三种方式

这篇具有很好参考价值的文章主要介绍了C#调用COM接口的三种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.准备工作

使用OLEView.exe查看本机安装的COM组件CLSID和接口Guid

  COM组件的提供者没有提供CLSID等信息或信息提供不全时,可以使用OleView.exe来查看其类和接口的GUID. OLEView.exe全称是OLE-COM Object Viewer,是Microsoft SDK中包含的一个工具,可以用来查看本机安装的所有COM组件的信息,包括CLSID、ProgID等。如果是完整的开发环境,其位置在C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin,非开发环境下也可以到网上下载该程序和它依赖的一个IVIEWERS.DLL.
  在All Objets中查看COM组件的CLSID,右键可以直接复制CLSID. 右键选中项,点击ViewTypeInfo可查看详细接口列表和接口的Guid。本次使用的COM组件只有一个callJson接口,一个字符串类型的输入参数([in]),一个输出参数作为返回值([out,retval])。

2.三种不同的引用方式

方式1 使用tlbimp生成类库直接引用

常见的COM组件是dll形式,在VS中可以直接添加引用,VS会自动生成一个Interop.xxx.dll类库。项目中使用的第三方COM组件是exe形式,可以使用tlbimp.exe手动转换。在Visual Studio的工具库中找到并打开VS的命令提示符,按格式输入指令tlbimp FILENAME /out:OUTPUT生成类库,类库生成之后就可以在VS中添加引用,然后像其他类库一样直接调用其中的接口。

方式2 使用CLSID和反射动态调用

已知COM类的CLISID时可以直接使用Type.GetTypeFromCLSID方法来获取COM组件的Type,然后动态创建对象调用接口。

private string CallJson(string input)
        {
            string ret = "";
            Type dycomType = Type.GetTypeFromCLSID(new Guid("xxxxxx"));

            if (dycomType != null)
            {
                //创建类实例
                dynamic dycomObject = Activator.CreateInstance(dycomType);
                //调用
                ret = dycomObject?.callJson(input);
            }

            return ret;
        }

也可以使用ProgId来获取:

Type t = Type.GetTypeFromProgID("TestComServer.TestComVisibleClass");
dynamic o = Activator.CreateInstance(t);

方式3 ComImport方式引用

使用ComImport标签引用COM组件,需要写明类的Guid和接口的Guid:

    [ComImport, Guid("xxxxxxxxxxxx")]
    class DycomObject
    {

    }
    // Declare IMediaControl as a COM interface which 
    // derives from the IDispatch interface. 
    [Guid("xxxxxxxx"),
        InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
    interface IDycomObject // cannot list any base interfaces here 
    {
        // Note that the members of IUnknown and Interface are NOT
        // listed here 
        //
        [return: MarshalAs(UnmanagedType.BStr)]
        object callJson(
        [In, MarshalAs(UnmanagedType.BStr)] string request);

    }

调用: 

 

      private string CallJson(string input)
        {
            string ret = "";
            Console.WriteLine("创建类实例");
            DycomObject dy = new DycomObject();
            IDycomObject iDy = (IDycomObject)dy;
            Console.WriteLine("调用");
            ret = (string)iDy.callJson(input);
            return ret;
        }

实际项目中的问题

  上述三种方式的接口格式都是一个输入参数对应COM接口的[in]参数,一个返回值对应[out,retval]参数,按照第三方接口描述,返回值中包含接口调用结果和错误码。实际使用中发现,调用出错时,接口会返回一个非零的HRESULT,同时把错误信息传给[out,retval]参数,但.Net会把非零的HRESULT转换为一个异常抛出,导致以上三种写法的返回值都为null,无法获取错误信息。在社区发帖问到了解决方法,就是需要修改方式3的引用方式,使用[PreserveSig]取消COM互操作期间的HRESULT和retval签名转换,让错误信息可以被正常接收到:

[ComImport, Guid("xxxxxx")]
    class DycomObject
    {

    }
    [ComVisible(true), ComImport, Guid("xxxxxx")]
    interface IDycomObject
    {
        [PreserveSig]
        int callJson(
            [In,MarshalAs(UnmanagedType.BStr)]
            string request, 
            [Out,MarshalAs(UnmanagedType.BStr)]
            out string response);
    }

    private string CallJson(string input)
    {
        string ret = "";
        Console.WriteLine("创建类实例");
        DycomObject dy = new DycomObject();
        IDycomObject iDy = (IDycomObject)dy;
        Console.WriteLine("调用");
        var code = iDy.callJson(input,out ret);
        return ret;
    }

 文章来源地址https://www.toymoban.com/news/detail-441068.html

到了这里,关于C#调用COM接口的三种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • AIGC: 关于ChatGPT中API接口调用相关准备工作

    ChatGPT之API接口相关 通过页面和GPT交流获取信息相比直接调用GPT的API而言是非常有限的 页面上的GPT是比较封闭的,而且只允许我们去输入文本的信息 我们需要借助GPT的API开发来激发AI工具的无限可能,实现更多个性化需求 1 ) 使用API 使用API有一个前置的条件 注册ChatGPT账号

    2024年02月04日
    浏览(52)
  • C#使用post方式调用接口获取Token及调用网页地址

     IP、Port表示地址及端口,可配置或写死 public string PostDate(string IP,string Port)         {             //设置参数             string content= \\\"{\\\"userName\\\":\\\"\\\" 0000 \\\"\\\"\\\" +                  \\\",\\\"password\\\":\\\"123456\\\"}\\\";             //填充路径             string strUrl = string.Format(\\\"http://{0}:

    2023年04月08日
    浏览(37)
  • python调用父类方法的三种方式(super调用和父类名调用)

    父类名.方法名(self) super(子类名,self).父类方法名() super().父类方法名 注意:super()通过子类调用当前父类的方法,super默认会调用第一个父类的方法(适用于单继承的多层继承 如下代码: 如下代码: 上面代码运行结果: 针对这种情况,正确的做法是定义Person类自己的构造方法

    2024年02月06日
    浏览(58)
  • java对接第三方接口的三种方式

    在日常工作中,经常需要跟第三方系统对接,我们做为客户端,调用他们的接口进行业务处理,常用的几种调用方式有: 1.原生的Java.net.HttpURLConnection(jdk); 2.再次封装的HttpClient、CloseableHttpClient(Apache); 3.Spring提供的RestTemplate; 当然还有其他工具类进行封装的接口,比

    2024年04月28日
    浏览(61)
  • spring boot请求http接口的三种方式

    HttpURLConnection 是 Java 中的 HTTP 客户端实现,,适用于简单的请求需要。 HttpURLConnection主要工作内容:打开socket连接,封装http请求报文,解析请求报文。 OkHttp 是一个第三方的 HTTP 客户端库,它比 Java 标准的 HttpURLConnection 更高效、更实用。主要特点包括: 比 HttpURLConnection 快得多

    2024年02月14日
    浏览(61)
  • 【接口/性能测试】Jmeter引用 jar包的三种方式(详细)

    实现对登录密码进行MD5加密 pom文件依赖 MD5Util类 package打包生成jar文件。 方式一:把jar包加入到classpath 添加jar包 login请求 beanshell脚本 发送请求后,从查看结果树中可以看到请求的密码加密了 方式二:把jar包放到lib/ext下 jmeter会自动从它的/lib和/lib/ext目录下的jar包中查找需要

    2024年02月15日
    浏览(39)
  • 【接口测试】POST请求提交数据的三种方式及Postman实现

      POST请求是HTPP协议中一种常用的请求方法,它的使用场景是向客户端向服务器提交数据,比如登录、注册、添加等场景。另一种常用的请求方法是GET,它的使用场景是向服务器获取数据。 当前,POST请求提交数据的编码方式有三种: application/x-www-form-urlencoded multipart/form-dat

    2024年02月10日
    浏览(50)
  • C#蓝牙连接及传输数据的三种方式(蓝牙传输文件、二进制数据)

          先下载InTheHand.Net.Personal.dll并在C#中引用,这个需要在网上下载      先看界面            这种方式优点是稳定性较强,基本无错误,就是偶尔需要提前蓝牙配对。        这种方式直接与蓝牙设备进行配对的时候会报错,请求的地址无效,这时候需要在被检测的蓝牙

    2024年02月11日
    浏览(73)
  • uni-app中调取接口的三种方式与封装uni.request()

    1、uni.request({}) 2、uni.request({}).then() 3、async/await 1、创建一个对象,将该对象挂在Vue的原型下 新建 @/common/request.js 文件 初步写法(仅供参考): 二次更改: 2、进入main.js文件 例:在任意文件中书写下列代码可以调用。 this.$Z.get(); 3、在页面中调用 uniapp的网络请求方法 CODE u

    2024年02月09日
    浏览(47)
  • 7. 【可编程并行接口8255】:接口特点、结构、引脚、三种工作方式、控制字、方式0应用、设计简易安全报警系统

    基本输入/输出方式 (方式0) 选通工作方式 (方式1) 双向传送方式 (方式2) 相当于三个独立的8位简单接口,可输入或输出 各端口既可设置为输入口,也可设置为输出口,但不能同时实现输入及输出 C端口可以是一个8位的简单接口,也可以分为两个独立的4位端口 常用于

    2024年02月06日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包