■■■■前言

目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用。使用C#调用ActiveX控件时一般是使用vs.net工具自动生成的互操作性程序集。这种方法操作简单,能保证一定的性能。但会产生额外的程序文件,不利于应用软件的简洁部署,还容易产生和ActiveX控件版本相关的错误。本文就提出使用反射技术动态调用ActiveX控件的方式来解决这些问题。

 

■■■■问题描述:

目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用。使用C#调用ActiveX控件时一般是使用vs.net工具的添加COM引用时自动生成的互操作性程序集。这种方法操作简单,能保证一定的性能。但会产生额外的程序文件,不利于应用软件的简洁部署。而且当开发环境和运行环境使用的ActiveX控件的版本不一致[袁永福原创]时还容易出错。

笔者长期从事基于.NET平台的通用产品类软件研发。[袁永福原创]产品类软件要求部署简洁,为此笔者都会将多个工程编译生成的多个.NET程序集文件合并成一个.NET程序集文件来做到简洁部署。

实践中发现自动生成的互操作性程序集无法合并。另外产品类软件应该能适应各种复杂的开发和生产环境,甚至ActiveX控件的CLSID 都有可能变化。

例如,对于COM类库“HebcaFormSealLib”,VS.NET会自动生成程序集文件“AxInterop.HebcaFormSealLib.dll”、“Interop.HebcaFormSealLib.dll”。这些程序集文件无法进行程序集合并,而且对于32位或64位的工程项目类型敏感,容易导致错误。

■■■■技术改进:

因此笔者不采用这种自动生成的互操作性程序集。转而采用自定义的反射来调用ActiveX控件。

后期绑定ActiveX 控件主要知识点为System.Windows.Forms.AxHost类型和Type.InvokeMember方法。

AxHost类型是从System.Windows.Forms.Control类型[袁永福原创]派生出来的,专门用于承载ActiveX控件。它是一个抽象类,有一个受保护的构造函数,函数参数是一个guid格式的ActiveX控件的CLSID字符串。还有一个GetOcx内部方法用于创建ActiveX控件的对象实例,它是一个COM对象引用。

创建了这个COM对象引用后就可以调用Type.InvokerMember方法来动态的调用指定名称的方法和属性。

■■■■范例:

笔者最近在使用某电子签名的ActiveX控件来实现文档签名的功能。笔者写出以下接口代码

 
[System.Runtime.InteropServices.ComVisible(false)]
public class DCHebeiCAControl : System.Windows.Forms.AxHost
{
    public DCHebeiCAControl()
        : base("{e4ee564c-0845-4404-91ee-0c206113333f}")
    { }
    public object _ocx = null;
    protected override void AttachInterfaces()
    {
        this._ocx = base.GetOcx();
    }
    private void CheckOCX()
    {
        if (this._ocx == null)
        {
            throw new System.NullReferenceException("_ocx");
        }
    }
    public VersionType GetBaseVersionType()
    {
        this.CheckOCX();
        VersionType result = (VersionType)this._ocx.GetType().InvokeMember(
            "GetBaseVersionType",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }
    public string GetCert(string sealSN)
    {
        this.CheckOCX();
        string result = (string)this._ocx.GetType().InvokeMember(
            "GetCert",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { sealSN });
        return result;
    }
    public string GetClientDetailVersionInfo()
    {
        this.CheckOCX();
        string result = (string)this._ocx.GetType().InvokeMember(
            "GetClientDetailVersionInfo",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }
    public int GetClientVersion()
    {
        this.CheckOCX();
        int result = (int)this._ocx.GetType().InvokeMember(
            "GetClientVersion",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }
    public string GetClientVersionInfo()
    {
        this.CheckOCX();
        string result = (string)this._ocx.GetType().InvokeMember(
            "GetClientVersionInfo",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { });
        return result;
    }
    public object GetConfig(string argName)
    {
        this.CheckOCX();
        object result = (object)this._ocx.GetType().InvokeMember(
            "GetConfig",
            BindingFlags.InvokeMethod,
            null,
            this._ocx,
            new object[] { argName });
        return result;
    }
    // ----------- 封装其他接口 -----------------------------
}//classDCHebeiCAControl
 

上述代码中各个功能函数内部代码结构简单[袁永福原创],之间有很大的相似性,因此完全可以编写一个代码生成器来自动生成上述代码。

完成自定义的控件后,笔者再创建一个WinForm 窗体,在其Load事件中创建控件并添加到窗体上,其代码如下

这样无需使用自动生成的COM接口程序集即可调用ActiveX控件,大幅提高程序

private DCHebeiCAControl _Control = null;
private void frmTest_Load(object sender, EventArgs e)
{
    this._Control = new DCHebeiCAControl();
    this._Control.Size = new Size(200, 200);
    this._Control.Location = new Point(0, 0);
    this.Controls.Add(this._Control);
}
 

的通用性,而且对于32位和64位的项目类型不敏感。方便部署和更新。

不过这样由于采用后期绑定而带来一定的性能[袁永福原创]问题,因此对于性能敏感而又频繁调用ActiveX控件的场景下需要谨慎采用这种模式。

■■■■小结:

在.net开发中调用旧的ActiveX控件是很多开发场景中不得不做的事情。在本文中,笔者介绍了在C#中调用ActiveX控件的标准模式,并提出了一种[袁永福原创]改良模式来提高程序的通用性。为操作ActiveX控件的.NET程序开发提供了一种新的技术手段。

袁创:使用反射动态调用ActiveX控件的更多相关文章

  1. 使用反射动态调用ActiveX控件

    使用反射动态调用ActiveX控件 袁永福 2018-3-2 ■■■■问题描述: 目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用.使用C#调用ActiveX控件时一 ...

  2. 【VS开发】使用MFC创建并调用ActiveX控件

    使用MFC创建并调用ActiveX控件 今天做了一下ActiveX的使用测试,总结一下: 首先使用MFC创建一个activeX的控件譬如ActiveXTest,编译成ocx并注册,然后另外编写一个测试 ...

  3. C#调用ActiveX控件

    背景:最近项目中需要用到ActiveX控件,项目是在.Net平台下开发的.因此就直接在项目中添加了对ActiveX控件的引用,添加引用成功.在代码中实例化类的实例也没有问题,但在调用其方法或属性时总是 ...

  4. ie 64bit调用activex控件

    1,首先,这是可能的.不要被网上一堆ie64调不了activex控件的文章误导了.flash就是一个现成的例子,flash支持ie64. 2,ie64只能调用64bit的activex控件.网上那些说 ...

  5. 【VS开发】动态创建ActiveX控件

    bool CCollectDataDlgDlg::CreateMyCtrl(LPRECT lpRect, UINT nID, CWnd *pParent) {  CLSID clsid;  wstri ...

  6. 谷歌浏览器调用activex控件方法

    原文转自 https://jingyan.baidu.com/article/af9f5a2d0ebe5543140a4596.html activex是由微软开发,所以在支持上,目前原生态支持的只有 ...

  7. 【转】Win32程序中调用ActiveX控件

    #include "stdafx.h" #include <iostream> #include <windows.h> #include <comd ...

  8. 让动态创建的ActiveX控件响应Windows消息

    当我们通过 CWnd::CreateControl() 动态创建 ActiveX   控件时, Windows 消息并不会被发送给我 们的由   CWnd 派生得控件类.例如,即使我们为 WM_KIL ...

  9. Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件

    若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期持续带来更多项目与技术分享 ...

随机推荐

  1. -1-3 java集合框架基础 java集合体系结构 Collection 常用java集合框架 如何选择集合 迭代器 泛型 通配符概念 Properties 集合 迭代器

    集合又称之为容器存储对象的一种方式 •数组虽然也可以存储对象,但长度是固定的:显然需要可变长度的容器 集合和数组的区别?                 A:长度区别                  ...

  2. -1-7 java 网络编程基本知识点 计算机网络 TCP/IP协议栈 通信必备 tcp udp

    计算机网络 是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路连接起来, 在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统. 网络编程 ...

  3. 痞子衡嵌入式:并行接口NAND标准(ONFI)及SLC Raw NAND简介

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是ONFI标准及SLC Raw NAND. NAND Flash是嵌入式世界里常见的存储器,对于嵌入式开发而言,NAND主要分为两大类:S ...

  4. 用meterpreter实现跳板机

      meterpreter跳板机 背景:渗透测试者A拿到了B主机的控制权,但没有拿到ssh密码(不能打ssh隧道).现需横向移动渗透内网主机C,为了避免动作过大不便直接在B上对C进行渗透,其中C不能出 ...

  5. Linux 桌面双击运行脚本

    创建桌面文件 touch myapp.desktop 编辑此文件写入一下内容 [Desktop Entry] Name = myapp Exec = /usr/bin/xxxx/xxx.sh Icon ...

  6. centos-linux入门笔记

    一.linux的用户 linux的用户和windwos差不多,分为管理员用户和普通用户. 普通用户:权限没那么高而已. 管理员用户:在linux中就是root用户,所拥有的权限是最高的. 二.linu ...

  7. 手机端两端对齐,兼容ios,安卓

    .div-title p label{ text-align: justify; width: 18%; display: inline-block; text-align-last: justify ...

  8. Mapbox浅析(快速入门Mapbox)

    1.是什么? Mapbox是一个可以免费创建并定制个性化地图的网站. 2.了解一些基本东西 常见的 mapbox.js和mapbox-gl.js的异同点? 相同点: 1.都是由Mapbox公司推出的免 ...

  9. android FragmentTabhost导航分页

    基本模板 public class MainActivity extends FragmentActivity { private FragmentTabHost mTabHost; private ...

  10. gitbook 入门教程之插件介绍

    插件是 gitbook 的扩展功能,很多炫酷有用的功能都是通过插件完成的,其中插件有官方插件和第三方插件之分. 推荐官方插件市场 https://plugins.gitbook.com/ 寻找或下载相 ...