一、前言

最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信、调用,单单依靠HTML是无法实现了,因此必须借用Activex来实现。由于本人主要擅长C#,自然本文给出了用C#实现的范例,本文的预期效果是有一定Winform基础的人可都轻松读懂本文。

文章主要介绍了以下几个部分:
 
1、用C#制作Activex控件,并发布为msi安装文件
 
2、将msi打包为cab,达到浏览器自动安装的效果
 
3、给cab数字签名(可选)
 
4、将Activex应用到网页上
 
二、用C#制作Activex控件,并发布为msi安装文件
 
1)新建window用户控件项目EasyActivex。其实VS2010并没有提供专门的Activex项目模板,所谓的Activex,只要符合com标准即可。
 
 
 
 
2)在EasyActivex项目添加IObjectSafety接口
 
 
在IObjectSafety接口代码如下,值得注意的是Guid不能随便改,必须为一下代码给出的Guid:
 

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices; namespace EasyActivex
{ [ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); [PreserveSig()]
int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
}
}
3)在EasyActivex项目添加EUserControl控件,在控件中实现IObjectSafety接口。
 
 
在控件上面添加按钮,命名为btnOpenNote
 
 
控件的后台代码必须实现IObjectSafety接口
 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace EasyActivex
{
//这个Guid,网页调用的时候用到,Mark
[Guid("685F0A47-944D-4145-BF4E-76A02A422B02")]
//这里要实现IObjectSafety接口
public partial class EUserControl : UserControl, IObjectSafety
{
public EUserControl()
{
InitializeComponent();
}
#region IObjectSafety 接口成员实现(直接拷贝即可) private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = ;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true; public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
{
int Rslt = E_FAIL; string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = ;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = ;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
} public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
{
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
Rslt = S_OK;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
Rslt = S_OK;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
} #endregion /// <summary>
/// 打开记事本
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnOpenNote_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start("notepad.exe");
}
}
}

小提示:EUserControl代码的Guid可以用VS附带的Guid生成工具生成:

 
4)在EasyActivex项目AssemblyInfo.cs文件中添加代码
 
 
 
//用户添加
[assembly: AllowPartiallyTrustedCallers()]
5)设置EasyActivex项目项目属性为com互操作
 
 
6)新建windows程序安装项目EasySetup
 
 
7)将EasyActivex项目生产的dll添加到EasySetup项目中。下图的EasyActivex.dll为已经添加进去了的文件。
 
 
8)在EasySetup项目中,设置EasyActivex.dll文件属性为vsdraCOM。
 
 
完成以上步骤,生成下即可得到msi安装文件
 
三、将msi安装文件打包为cab,达到在浏览器中自动安装的效果
 
如果只是生成了msi文件,用户安装的时候比较麻烦,像安装一般软件一样,需要用户慢慢点击下一步,慢慢安装,在本项目中采用打包成cab文件的方式,做到用户点击运行后,即可自动安装。
在这里需要准备文件有:
    cabarc.exe:微软提供的cab打包工具
    EasySetup.msi:  本案例中EasySetup项目生成的windows部署安装文件
    install.inf : 需要跟EasySetup.msi打包在一起的文件,制作方法请见下文
    build.bat:  打包的批处理命令,制作方法请见下文
 
1)  install.inf制作。新建txt文件,加入以下内容,将文件名重新命名为install.inf即可。其中EasyZSetup.msi即是要打包的安装程序的名称。
[version]
signature="$CHICAGO$"
AdvancedINF=2.0 [Setup Hooks]
hook1=hook1 [hook1]
run=msiexec.exe /i "%EXTRACT_DIR%\EasySetup.msi" /qn

2)   build.bat制作。新建txt文件,加入以下内容,将文件名重新命名build.bat即可。其中EasyActivex.cab是生成目标cab的名称;install.inf是第一步生成的文件名,而EasySetup.msi是需要打包的安装程序名;第二条ping命令仅仅是让批处理不要那么快退出,起到更利于观察生成结果的作用。

"cabarc.exe" -s  n EasyActivex.cab install.inf EasySetup.msi
ping -n 127.0.0.1 >nul
 把以上四个文件复制到同一个文件夹中,双击build.bat批处理命令即可生成cab文件
 
 
双击bat后的运行结果如下,其中EasyActivex.cab即是生成的目标cab文件。
 
 
 
三、给cab数字签名(可选)
 
     由于处于安全问题考虑,IE浏览器设置默认是禁用未签名的Activex控件的,不过想想也知道,假如打开个未知网页,“网页”就能随便调用计算机本地的东西是多么恐怖的事情,因此,浏览器运行的Activex必须是签名了的,也符合常理。
     如果不怕用户麻烦,不采用cab签名的方式的话,也可以通过设置浏览器安全性来运行Activex。设置方法:打开浏览器--浏览器Internet选项--安全选项卡--自定义级别按钮-下载未签名的Activex控件设置为提示,保存即可。等安装完毕后,可以将“下载未签名的Activex控件”设置回禁用。
   以下为给cab签名的方法,具体方法,数字认证网上面已经介绍得很详细:
 
   1)申请、安装证书。上中国数字认证网(http://www.ca365.com/)申请一个免费数字证书(试用期为1年,如果企业用的话需要购买)。 
        操作方法:http://www.ca365.com/forward.do?pageurl=/ca/yhsc/4.jsp ,值得注意的是证书用途必须选择代码签名证书。
        申请成功后的证书,由于是不带密钥的,因此下载完毕后只能够在申请证书的机器上安装、使用(签名文件),如果需要在其他机器上使用的话需要将密钥导出,操作方法为: http://www.ca365.com/forward.do?pageurl=/ca/yhsc/5.jsp 。
 
  2)用证书给cab包签名:http://www.ca365.com/forward.do?pageurl=/ca/thsc/7.jsp 
 
四、在解决方案中添加EasyWeb项目
 
    终于到了最后一步,发布鸟。在解决方案中添加EasyWeb项目
 
 
 
在网页目录中新建Activex文件夹,并将EasyActivex.cab文件拷贝进去
 
 
在网页中添加以下代码,即可调用Activex控件了。值得注意的是codebase是cab包的相对路径;clsid是EUserControl控件的Guid。
 
 <object id="csharpActiveX" codebase="Activex/EasyActivex.cab" classid="clsid:685F0A47-944D-4145-BF4E-76A02A422B02"></object>

运行效果如下:

点击即可在网页中打开记事本了。

五、本案例源码+cab打包工具+数字签名工具下载

六、参考资料:

1、使用C#开发ActiveX控件  http://www.cnblogs.com/yilin/archive/2009/09/15/1567332.html

2、Activex签名方法和工具技巧  http://www.360doc.com/content/10/0901/15/203871_50402416.shtml

3、中国数字认证网用户手册 http://www.ca365.com/forward.do?pageurl=/ca/yhsc.jsp

C#制作、打包、签名、发布Activex全过程的更多相关文章

  1. 发布Activex全过程

    C#制作.打包.签名.发布Activex全过程 一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠HTML是无法实现了,因此必须借用Activex来实现.由于 ...

  2. EclipseAndroid打包签名发布安装失败闪退运行不了

    EclipseAndroid打包签名发布安装失败闪退运行不了 本来没怎么用过用Eclipse写安卓,可是有人有需要必须用Eclipse写,那就写呗. 可在签名打包的时候,发到手机上安装,提示安装成功. ...

  3. C# winFrom 制作、打包、签名、发布Activex全过程

    注:转自园中 http://www.cnblogs.com/still-windows7/p/3148623.html 一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调 ...

  4. C#制作、打包、签名、发布Activex全过程【转】

    http://www.cnblogs.com/still-windows7/p/3148623.html 一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠H ...

  5. ionic3应用的Android打包签名发布步骤

    版权声明:本文为博主原创文章,未经博主允许不得转载. 当我们的ionic应用开发结束之后,就要开始上线到应用市场,那么Android的发布步骤具体是怎么样的呢? 1)编译 运行命令行: ionic c ...

  6. Android Studio 打包签名发布New Key Store

    Key store path:存放路径 Key Alias:别名 Validity(years):有效期 Certificate:证书 First and Last Name: Organizatio ...

  7. Activex打包于发布完整版---微软证书制作

    众所周知,Activex组件没有进行有效的签名,在IE上无法安装的,除非你让用户手工开启“接收任何未签名的ActiveX”,这个很明显不现实.而组件签名需要证书,证书从哪里来,你可以选择付1000到3 ...

  8. DotNetBar for Windows Forms 14.0.0.15_冰河之刃重打包版发布

    关于 DotNetBar for Windows Forms 14.0.0.15_冰河之刃重打包版 --------------------11.8.0.8_冰河之刃重打包版------------- ...

  9. Android打包签名

    Ⅰ.用jdk和sdk自带工具打包签名 a.把jdk下的keytool.exe和jarsigner.exe所在目录(两个工具在同一目录) 添加到环境变量path 1)新建环境变量package,pack ...

随机推荐

  1. 使用C#处理基于比特流的数据

    使用C#处理基于比特流的数据 0x00 起因 最近需要处理一些基于比特流的数据,计算机处理数据一般都是以byte(8bit)为单位的,使用BinaryReader读取的数据也是如此,即使读取bool型 ...

  2. Bootstrap 模态框(Modal)插件

    页面效果: html+js: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...

  3. 在 C# 里使用 F# 的 option 变量

    在使用 C# 与 F# 混合编程的时候(通常是使用 C# 实现 GUI,F#负责数据处理),经常会遇到要判断一个 option 是 None 还是 Some.虽然 Option module 里有 i ...

  4. Android带加减的edittext

    看了网上这样自带加减的edittext写得好复杂,还有各种监听事件,我觉得没有必有.于是我自己写了一个. 我这个edittext仅仅限制整数,每次加减1. public class TestEditT ...

  5. Java 为值传递而不是引用传递

    ——reference Java is Pass by Value and Not Pass by Reference 其实这个问题是一个非常初级的问题,相关的概念初学者早已掌握,但是时间长了还是容易 ...

  6. Javascript实现HashTable类

    散列算法可以尽快在数据结构中找出指定的一个值,因为可以通过Hash算法求出值的所在位置,存储和插入的时候都按照Hash算法放到指定位置. <script> function HashTab ...

  7. JavaScript基础知识总结(二)

    JavaScript语法 二.数据类型 程序把这些量.值分为几大类,每一类分别叫什么名称,有什么特点,就叫数据类型. 1.字符串(string) 字符串由零个或多个字符构成,字符包括字母,数字,标点符 ...

  8. 【干货分享】流程DEMO-借款申请

    流程名: 借款申请   业务描述: 当员工个人在工作中需要进行借款时,通过此项流程提交借款申请,审批通过后,财务部进行款项支付.   流程相关文件: 流程包.xml WebService业务服务.xm ...

  9. XAMARIN.ANDROID SIGNALR 实时消息接收发送示例

    SignalR 是一个开发实时 Web 应用的 .NET 类库,使用 SignalR 可以很容易的构建基于 ASP.NET 的实时 Web 应用.SignalR 支持多种服务器和客户端,可以 Host ...

  10. JQuery阻止事件冒泡

    冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件. 我们在平时的开发过程中,肯定会遇到在一个div(这个div可以是元素)包裹一个div的情况,但是呢,在这两个div上都添加了事件,如果点 ...