使用反射动态调用ActiveX控件
使用反射动态调用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控件的更多相关文章
- 袁创:使用反射动态调用ActiveX控件
■■■■前言 目前的基于.NET平台的软件研发中仍然存在大量的对COM及ActiveX控件的调用.使用C#调用ActiveX控件时一般是使用vs.net工具自动生成的互操作性程序集.这种方法操作简单, ...
- 【VS开发】使用MFC创建并调用ActiveX控件
使用MFC创建并调用ActiveX控件 今天做了一下ActiveX的使用测试,总结一下: 首先使用MFC创建一个activeX的控件譬如ActiveXTest,编译成ocx并注册,然后另外编写一个测试 ...
- C#调用ActiveX控件
背景:最近项目中需要用到ActiveX控件,项目是在.Net平台下开发的.因此就直接在项目中添加了对ActiveX控件的引用,添加引用成功.在代码中实例化类的实例也没有问题,但在调用其方法或属性时总是 ...
- ie 64bit调用activex控件
1,首先,这是可能的.不要被网上一堆ie64调不了activex控件的文章误导了.flash就是一个现成的例子,flash支持ie64. 2,ie64只能调用64bit的activex控件.网上那些说 ...
- 【VS开发】动态创建ActiveX控件
bool CCollectDataDlgDlg::CreateMyCtrl(LPRECT lpRect, UINT nID, CWnd *pParent) { CLSID clsid; wstri ...
- 谷歌浏览器调用activex控件方法
原文转自 https://jingyan.baidu.com/article/af9f5a2d0ebe5543140a4596.html activex是由微软开发,所以在支持上,目前原生态支持的只有 ...
- 【转】Win32程序中调用ActiveX控件
#include "stdafx.h" #include <iostream> #include <windows.h> #include <comd ...
- 让动态创建的ActiveX控件响应Windows消息
当我们通过 CWnd::CreateControl() 动态创建 ActiveX 控件时, Windows 消息并不会被发送给我 们的由 CWnd 派生得控件类.例如,即使我们为 WM_KIL ...
- Qt开发Activex笔记(二):Qt调用Qt开发的Activex控件
若该文为原创文章,转载请注明原文出处本文章博客地址:https://blog.csdn.net/qq21497936/article/details/113789693 长期持续带来更多项目与技术分享 ...
随机推荐
- 痞子衡嵌入式:第一本Git命令教程(3)- 变动(status/diff)
今天是Git系列课程第三课,前两课我们都是在做Git仓库准备工作,今天痞子衡要讲的是如何查看Git空间内发生的改动. 本地有了仓库,我们便可以在仓库所在目录下做文件增删改操作,为了确定改动操作的正确性 ...
- 第17章 社区快速入门和模板 - Identity Server 4 中文文档(v1.0.0)
IdentityServer组织不维护这些示例.IdentityServer组织愉快地链接到社区模板,但不能对模板做出任何保证.请直接与作者联系. 17.1 各种ASP.NET核心安全样本 https ...
- 杭电ACM2015--偶数求和
偶数求和 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- Mysql is null 索引
看到很多网上谈优化mysql的文章,发现很多在谈到mysql的null是不走索引的,在此我觉得很有必要纠正下这类结论.mysql is null是有索引的,而且是很高效的,(版本:mysql5.5)表 ...
- HTTP协议的六种请求方法
抛砖引玉,聊下概念性的东西先: HTTP协议 (Hyper Text Transfer Protocol) HTTP是一个基于TCP/IP通信协议来传递数据,包括html文件.图像.结果等,即是一个客 ...
- java Calendar的学习分享
前言: 在我们的日常生活中,常常能看见时间.如:在我们的手机里,在一些网站上也能随处看到时间.那我们在项目的开发中,也常常涉及到时间的处理,对于我们经常会遇到和处理的问题.Java中专门为我们处理时间 ...
- kafka配置记录
1. 准备三台机器,系统CentOs6 2. 安装好JDK和zookeeper 参考: zookeeper配置记录 3. 解压安装包到指定目录 tar -zxvf kafka_2.12-2.1.0.t ...
- Django学习之五:Django 之 注意事项及汇总
目录 Django 之 注意事项及汇总 全局 settings model模块-模型模块 URLs模块 Templates System 模版模块 View/HttpRequest/HttpRespo ...
- 《Odoo开发指南》精选分享—第1章-开始使用Odoo开发(1)
引言 在进入Odoo开发之前,我们需要建立我们的开发环境,并学习它的基本管理任务. 在本章中,我们将学习如何设置工作环境,在这里我们将构建我们的Odoo应用程序.我们将学习如何设置Debian或Ubu ...
- jquery获取内容和属性的方法
通过jquery如何捕获文本内容和属性? text(),html(),val()及attr(). attr()更具有普遍性,元素text属性和表单value属性,可以通过attr()操作. <! ...