win7下VS2010 C# ActiveX控件制作(附原码)
原码以及makeCAB包下载地址:http://files.iyunv.com/zouyang/HelloDaniel.rar
一、环境:
操作系统:Win7
开发工具:Visual Studio 2010
.NET版本:4.0
开发语言:C#
下载makeCAB压缩包,这里面包含了制作数字签名和制作cab的几个exe程序
保存路径:D:\makeCAB
需要编辑的系统环境变量设置:(下面的系统变量)
这样做是为了方便后面在cmd里调用。
二、编写ActiveX控件
1、创建一个新的Windows窗体控件库
2、重命名UserControl1.cs 为HelloDanielActiveX.cs
3、拖1个GroupBox和2个Label控件到界面上
4、为控件添加一个方法,用来设置Label中显示当前时间
#region Javascript调用ActiveX的方法
// 设置当前时间
public void SetTime(string timeStr)
{
this.label2.Text = timeStr;
}
#endregion
5、新建一个接口
下面是这个接口的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace HelloDaniel
{
public interface IObjectSafety
{
int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions,
ref int pdwEnabledOptions);
int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask,
int dwEnabledOptions);
}
}
6、在控件中实现这个接口
关于实现这个接口,篇幅较长,可以在这篇文章找到:http://www.pinvoke.net/default.aspx/Interfaces/IObjectSafety.html
7、为控件添加Guid、ProgId和ComVisible属性
Guid的获得应该是这样的:
点击复制,然后将你得到的Guid号Copy下,粘贴到下面代码里面。
然后,右键单击项目HelloDaniel——>属性,在应用程序中选择程序集信息
把使程序集COM可见的对勾打上。
同时,在属性——>【生成】项中选择为COM互操作注册
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using mshtml;
using System.Reflection;
namespace HelloDaniel
{// {6DCD51C2-33FD-4556-842F-419B6AA3C252}
public partial class HelloDanielActiveX : UserControl, 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 = 0;
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 HelloDanielActiveX()
{
InitializeComponent();
}
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 = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
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;
}
#region Javascript调用ActiveX的方法
///
/// 设置当前时间
///
///
public void SetTime(string timeStr)
{
this.label2.Text = timeStr;
}
#endregion
#region ActiveX调用Javascript的函数 方法一
///
/// HTMLWindow2Class对象
///
private mshtml.IHTMLWindow2 html = null;
///
/// 调用Javascript
///
///
///
private void button1_Click(object sender, EventArgs e)
{
html.execScript("CallByActiveX('" + this.label2.Text + "');", "javascript");
//CallJavaScript(this.label2.Text);
}
///
/// 将window对象传递进来
///
/// The obj.
public void SetHtml(object obj)
{
html = obj as mshtml.IHTMLWindow2;
}
#endregion
#region ActiveX调用Javascript的函数 方法二
///
/// 调用Javascript
///
/// The filenames.
private void CallJavaScript(string param)
{
//反射获取当前的控件的ClientSite
Type typeIOleObject = this.GetType().GetInterface("IOleObject", true);
object oleClientSite = typeIOleObject.InvokeMember("GetClientSite",
BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
this,
null);
//获取Container
IOleClientSite oleClientSite2 = oleClientSite as IOleClientSite;
IOleContainer pObj;
oleClientSite2.GetContainer(out pObj);
//参数数组
object[] args = new object;
args = param;
//获取页面的Script集合
IHTMLDocument pDoc2 = (IHTMLDocument)pObj;
object script = pDoc2.Script;
try
{
//调用JavaScript方法OnScaned并传递参数,因为此方法可能并没有在页面中实现,所以要进行异常处理
script.GetType().InvokeMember("ShowNowTime", BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public,
null,
script,
args);
}
catch { }
}
#endregion
}
}
代码里添加了两个在控件中实现javascript的方法。
8、为了实现在控件中javascript的调用,需要添加引入
右键单击项目HelloDaniel——>【添加引用】
9、生成项目,进入到你的项目文件夹bin\debug目录下可以看到
二、制作ActiveX Setup安装文件
1、右键解决方案——>添加——>新建项目
在其他项目类型——>安装和部署——>安装项目
2、在新建的项目上点右键,【添加】——>【项目输出】,如图操作。
3、生成项目
会生成两个安装程序。
剩下的工作就是打包签名部署到网页上测试了
三、打包生成cab文件
1、准备打包文件,建议新建个文件夹用来做cab包
我放在D盘下新建的ActiveX文件夹内
其中install.inf配置文件如下:
signature="$CHICAGO$"
AdvancedINF=2.0
HOOKRUN1=HOOKRUN1
InstallScope=machine
run=%EXTRACT_DIR%\run.bat
run.bat内容如下:
set CURDIR=%cd%
msiexec.exe /i "%CURDIR%\HelloDanielSetup.msi" /qn
2、打包cab
【开始】——【运行】——输入CMD
进入你新建的文件夹目录下(ActiveX),输入命令:
CABARC -s 6144 n HelloDaniel.cab HelloDanielSetup.msi install.inf run.bat
3、给cab数字签名
这里我需要求助一下,我在网上发现大家都是自己制作测试证书,但是我自己制作的证书签名后验证确实签名失败的。后来找到一个免费的数字签名工具(DSignTool)v1.7专业版,当然是做测试证书的。实验成功,大家可以下来试试,确实要方便的多,毕竟coder需要不断的测试嘛,下面是下载网址:
http://www.arpun.com/soft/9388.html
4、编辑网页测试
网页代码如下:
!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "
页:
[1]