使用反射动态调用ActiveX控件

袁永福 2018-3-2

■■■■问题描述:

目前的基于.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事件中创建控件并添加到窗体上,其代码如下

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);
}

这样无需使用自动生成的COM接口程序集即可调用ActiveX控件,大幅提高程序的通用性,而且对于32位和64位的项目类型不敏感。方便部署和更新。

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

■■■■小结:

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

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

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

    ■■■■前言 目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用.使用C#调用ActiveX控件时一般是使用vs.net工具自动生成的互操作性程序集.这种方法操作简单, ...

  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. 禁止用户打开HTML页面调试

    有些时候,我们可能想要禁止用户修改或者调试我们HTML页面的代码,这个时候需要组织用户打开调试窗口,下面介绍一些能够阻止用户在浏览器中打开调试窗口的方法,这些方法只能一定程度的提高打开调试的门槛,并不 ...

  2. ajax跨域请求,亲测有效

    跨域请求域有两种常用解决方案,jsonp和cors, 因为jsonp只能解决get请求问题,我这里用的是cors方法. js前端ajax请求: $.ajax({ url: "http://1 ...

  3. Java的几个基本类型之间的相互转换

    前言: 转载申明: 作者:王蒙 链接:http://matt33.com/2015/10/27/TheTransformOfJava/ 之前在写java程序的时候,经常会遇到很多的需要需要转换基础数据 ...

  4. 第38章 刷新令牌 - Identity Server 4 中文文档(v1.0.0)

    第38章 刷新令牌 由于访问令牌的生命周期有限,因此刷新令牌允许在没有用户交互的情况下请求新的访问令牌. 以下流程支持刷新令牌:授权代码,混合和资源所有者密码凭据流.需要明确授权客户端通过设置Allo ...

  5. 【默认加入持久化机制,防止消息丢失,v0.0.3】对RabbitMQ.Client进行一下小小的包装,绝对实用方便

    RabbitMQ是一个老牌的非微软的消息队列组件,一般来说应该能满足中小型公司对消息队列生产的需求,平时我们在.NET开发环境下运用它是可能会需要RabbitMQ.Client的SDK库,此库是官网提 ...

  6. pl/sql to_date

    to_date 函数:TO_DATE( string1 [, format_mask] [, nls_language] ) 后面两个函数为可选 ,意思将字符串类型转换为时间类型 , 可以自定义时间格 ...

  7. java开发环境配置——IDEA SVN的使用

    一.安装svn客户端,在idea中配置svn 装小乌龟,TortoiseSVN ,就下图一个要注意的地方,这里默认 command line client tools是不安装的,选上.如果已经安装过了 ...

  8. JAVA微信支付接口开发——支付

    微信支付接口开发--支付 这几天在做支付服务,系统接入了支付宝.微信.银联三方支付接口.个人感觉支付宝的接口开发较为简单,并且易于测试. 关于数据传输,微信是用xml,所以需要对xml进行解析. 1. ...

  9. Pythoy 数据类型序列化——json&pickle 模块

    Pythoy 数据类型序列化--json&pickle 模块 TOC 什么是序列化/反序列化 pickle 模块 json 模块 对比json和pickle json.tool 命令行接口 什 ...

  10. SSM登陆拦截器实现

    首先在springmvc中配置拦截器 <!-- 配置拦截器 --> <mvc:interceptors> <mvc:interceptor> <!-- 拦截所 ...