ActiveX接口 是一个开放的集成平台,为开发人员、用户和 Web生产商提供了一个快速而简便的在 Internet 和 Intranet 创建程序集成和内容的方法。 使用 ActiveX, 可轻松方便的在 Web页中插入 多媒体效果、 交互式对象、以及复杂程序,创建用户体验相当的高质量多媒体 CD-ROM

简单的说,用activeX和js差不多,但是有些是js无法实现的,这个时候就可以考虑一下activeX,一般要求是在客户端执行的程序,比如对本机的串口操作等,而服务器端不用做任何的操作和加载任何的插件,下面来简单介绍下如何用C#自己封装一个activeX组件,并在web中应用。

说明:我的这个例子是在实际工作中,需要把第三方厂家的C/S端动态库,封装为B/S端动态库。如果您的动态库不调用第三方厂家的动态库,可以在接口中去除链接即可。

开发工具:VisualStudio2012 (VisualStudio2017在添加用户控件后,自动生成匹配的程序代码集,故不推荐!)

步骤一:搭建开发环境

说明:选择类库,编辑好名称和路径位置。

步骤二: 更改“项目属性-应用程序-程序集信息”设置,勾选“使程序集 COM 可见”

说明:勾选COM有2处,都需要勾选

第一处:

第二处:

步骤三: 修改AssemblyInfo.cs文件,添加[assembly: AllowPartiallyTrustedCallers()]项(需要引用System.Security名称空间)

步骤三: 添加一个Windows用户控件

步骤四:防止浏览器一直弹出安全警告

为了提高程序的安全性,以便在客户端安装的时候在浏览器提高信任度,我们需要实现接口IObjectSafety

 1 using System;
2 using System.Collections.Generic;
3 using System.Text;
4 using System.Runtime.InteropServices;
5
6 namespace mProjectName
7 {
8 [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
9 [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
10 public interface IObjectSafety
11 {
12 [PreserveSig]
13 int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
14
15 [PreserveSig()]
16 int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
17 }
18 }

IObjectSafety

该类只是一个接口而已,我们还需要在自己的接口中去实现具体的方法。具体放置位置如下

提示:这部分代码都是通用的,不必做任何修改。

步骤五:用户控件的编写

首先,用户控件的设计部分:XXX.Designer.cs的模块,最好需要弄点图片或者文字加载到上面去,一边用浏览器加载的时候方便判断是否加载成功。

其次,编写主接口模块:

首先,第一个接口  ItfLyCnIcObject是用来给家口注册后,提供函数名称的,您可以用这个函数实现不懂的功能,当然接口的函数还没有实现的,是在下面的XXX_BObject 接口里面实现的。

ItfLyCnIcObject接口代码示例:

主体XXXIc_Object接口代码示例:

主体XXXIc_Object接口代码分为3部分,函数定义是为了加载第三方厂家的接口路径和方法,以及参数等,IObjectSafety接口是通用的,实现之前的IObjectSafety接口方法的具体实现,下面的具体方法是实现 ItfLyCnIcObject接口中方法的具体实现

IObjectSafety接口方法是公用的,无需修改:

 1         private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
2 private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
3 private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
4 private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
5 private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";
6
7 private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
8 private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
9 private const int S_OK = 0;
10 private const int E_FAIL = unchecked((int)0x80004005);
11 private const int E_NOINTERFACE = unchecked((int)0x80004002);
12
13 private bool _fSafeForScripting = true;
14 private bool _fSafeForInitializing = true;
15
16
17 public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
18 {
19 int Rslt = E_FAIL;
20
21 string strGUID = riid.ToString("B");
22 pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
23 switch (strGUID)
24 {
25 case _IID_IDispatch:
26 case _IID_IDispatchEx:
27 Rslt = S_OK;
28 pdwEnabledOptions = 0;
29 if (_fSafeForScripting == true)
30 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
31 break;
32 case _IID_IPersistStorage:
33 case _IID_IPersistStream:
34 case _IID_IPersistPropertyBag:
35 Rslt = S_OK;
36 pdwEnabledOptions = 0;
37 if (_fSafeForInitializing == true)
38 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
39 break;
40 default:
41 Rslt = E_NOINTERFACE;
42 break;
43 }
44
45 return Rslt;
46 }
47
48 public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
49 {
50 int Rslt = E_FAIL;
51
52 string strGUID = riid.ToString("B");
53 switch (strGUID)
54 {
55 case _IID_IDispatch:
56 case _IID_IDispatchEx:
57 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) &&
58 (_fSafeForScripting == true))
59 Rslt = S_OK;
60 break;
61 case _IID_IPersistStorage:
62 case _IID_IPersistStream:
63 case _IID_IPersistPropertyBag:
64 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) &&
65 (_fSafeForInitializing == true))
66 Rslt = S_OK;
67 break;
68 default:
69 Rslt = E_NOINTERFACE;
70 break;
71 }
72
73 return Rslt;
74 }

IObjectSafety接口具体实现

ItfLyCnIcObject中的方法实现中的方法名称和具体参数,以及个数都必须一致

之后,再从新生成无误后,会在bin文件的Debug文件中生成你封装好的dll

步骤六:注册该接口

这个得到的dll要和第三方厂家的dll放到一起(就是我们之前图片中的哪个第三方厂家的DLL),一并放到C:\Windows\SYSWOW64目录下,因为我的是windows64位电脑,如果你的电脑是32位的,一般放置到C:\Windows\System32目录下。

之后打开CMD,写入一下注册字符:

"C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" /codebase C:\Windows\SysWOW64\XXXXc_B.dll

具体截图如下:

然后回车即可注册成功。(中间可能有警告,不用管,只要有注册成功字样即可)

步骤七:接口的唯一ClassID查看

这个ClassID就是浏览器识别该该接口的唯一凭证,也就是说有了这个ClassID,一台电脑原则上可以注册无数的这种接口。可以通过接口查看器查看

我用的查看工具是oleview,大家可以用其他的看看,一般只要是正确的注册,都可以看到接口名称,如果没有看到,怎么能够接口没有注册成功。

步骤八:调用接口

新建一个html页面,添加下面的代码

具体代码分析:

到此,就基本上结束了,页面可以用JS来调用了,另外,浏览器的安全设置大家最好按网上其他大神说的那样设置就好。

由于这个是实际项目中的上线代码,故,内容可以不能全部公开,部分关键字段也做了刷白处理,可能对您观看造成不便,请多多包涵。如果大家有兴趣或者疑问,欢迎大家把疑问发送到我的邮箱1732182169@qq.com,或者直接QQ:1732182169联系我,大家一起学习探讨!

另外可以参考下面这位大神写的,也很不错:http://www.cnblogs.com/shuang121/archive/2012/06/04/2534296.html

c#封装ActiveX接口实践分析的更多相关文章

  1. QuantLib 金融计算——自己动手封装 Python 接口(2)

    目录 QuantLib 金融计算--自己动手封装 Python 接口(2) 概述 如何封装一项复杂功能? 寻找最小功能集合的策略 实践 估计期限结构参数 修改官方接口文件 下一步的计划 QuantLi ...

  2. 【lwip】06-网络接口层分析

    目录 前言 6.1 概念引入 6.2 网络接口层数据概念流图 6.3 网卡收包程序流图 6.4 网卡数据结构 6.4.1 struct netif源码 6.4.2 字段分析 6.4.2.1 网卡链表 ...

  3. Java中Comparable和Comparator接口区别分析

    Java中Comparable和Comparator接口区别分析 来源:码农网 | 时间:2015-03-16 10:25:20 | 阅读数:8902 [导读] 本文要来详细分析一下Java中Comp ...

  4. Android系统进程间通信Binder机制在应用程序框架层的Java接口源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6642463 在前面几篇文章中,我们详细介绍了A ...

  5. Java基础04 封装与接口

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 总结之前的内容,对象(object)指代某一事物,类(class)指代象的类型.对 ...

  6. CAN调度理论与实践分析

    CAN调度理论与实践分析 分布式嵌入式系统是当前嵌入式系统的重要发展方向,因为它能提供更强的性能,节约系统的总体成本.但是由于各单个节点必须有通信网络相连才能协调地工作,网络就成了关键部分,没有网络提 ...

  7. (转)专项:Android 内存泄露实践分析

    今天看到一篇关于Android 内存泄露实践分析的文章,感觉不错,讲的还算详细,mark到这里. 原文发表于:Testerhome: 作者:ycwdaaaa ;  原文链接:https://teste ...

  8. Java基础04 封装与接口(转载)

    数据成员和方法都是同时开放给内部和外部的.在对象内部,我们利用this来调用对象的数据成员和方法.在对象外部,比如当我们在另一个类中调用对象的时,可以使用 对象.数据成员 和 对象.方法() 来调用对 ...

  9. java Vamei快速教程04 封装和接口

    作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 总结之前的内容,对象(object)指代某一事物,类(class)指代象的类型.对 ...

随机推荐

  1. 3.Channel详解

  2. 结合源码谈谈ThreadLocal!

    目录 ThreadLocal的作用 ThreadLocal 1.对象初始化 2.获取变量 3.设置变量 4.移除变量 ThreadLocalMap 1.Entry 2.初始化 3.获取Entry 4. ...

  3. 获取NX一组属性

    NX中的属性是可以分组的,有时我们想获取某一个组下的所有属性,但是NX封装的接口不够好用,因此在此基础上,我封装了一个,供大家参考: 1 //属性值是字符串类型,obj对象tag,category组名 ...

  4. HTTP 的前世今生,那些不为人知的秘密

    每个时代,都不会亏待会学习的人. 大家好,我是 yes. HTTP 协议在当今的互联网可谓是随处可见,一直默默的在背后支持着网络世界的运行,对于我们程序员来说 HTTP 更是熟悉不过. 平日里我们都说 ...

  5. django 3.1 序列化讲述

    序列化Django对象¶ Django的序列化框架提供了一种将Django模型"翻译"为其他格式的机制.通常,这些其他格式将基于文本,并用于通过电线发送Django数据,但是序列化 ...

  6. Python-IndexError: list index out of range

    Error:IndexError: list index out of range Where? 对Python中有序序列进行按索引取值的时候,出现这个异常 Why? 对于有序序列: 字符串 str ...

  7. Java知识系统回顾整理01基础04操作符04位操作符

    一.位操作符 位操作符在实际工作中用的并不常见,但是我比较纠结这些位操作.所以实际练习位操作符的每一个操作符的操作实例来理解其具体含义. 建议: 如果确实感兴趣,就看看,个人建议跳过这个章节. 真正工 ...

  8. 一个Java对象的内存布局

    1.对象的创建过程 class loading class linking(verification,preparation,resolution) class initializing 申请对象内存 ...

  9. 【Office-Word妙手回春】Word文本秒转表格

    第一步:Ctrl+A组合键,文本全选 第二步:插入→表格→文本转换成表格 第三步:在"文字分隔位置",勾选相应的符号. 此处的分隔符为 空格. 点击"确定"按钮 ...

  10. Linux软件漏洞-1

    RHSA-2018:3107-中危: wpa_supplicant 安全和BUG修复更新 漏洞编号:CVE-2018-14526 漏洞公告:wpa_supplicant中未经身份验证的EAPOL-Ke ...