转自:http://lwchome.spaces.live.com/blog/cns!791B533443007D37!234.entry
前言:
这段时间因为工作的需要,研究了一下ActiveX控件。总结如下:
先说说ActiveX的基本概念。
根据微软权威的软件开发指南MSDN(Microsoft Developer Network)的定义,ActiveX插件以前也叫做OLE控件或OCX控件,它是一些软件组件或对象,可以将其插入到WEB网页或其它应用程序中。
ActiveX是Microsoft对于一系列策略性面向对象程序技术和工具的称呼,其中主要的技术是组件对象模型(COM)。在有目录和其它支持的网络中,COM变成了分布式COM(DCOM)。在创建包括ActiveX程序时,主要的工作就是组件,一个可以自足的在ActiveX网络(现在的网络主要包括Windows和Mac)中任意运行的程序。这个组件就是ActiveX近控件。ActiveX是Microsoft为抗衡Sun Microsystems的JAVA技术而提出的,此控件的功能和JAVA applet功能类似。
目前支持ActiveX的主要是IE浏览器。
以前ActiveX开发普遍使用VC++或VB,随着C#和.net的发布,用C#开发ActiveX控件变得更方便、更简单。但需要注意的是用C#开发 的ActiveX控件需要客户机装有.net framework,有点郁闷。可是相对.net强大的功能良好的易用性,这点牺牲还是值得的,况且现在好多计算机已经安装有.net framework了。
其实.net下的winform控件也是可以直接嵌入到web网页里的,但是由于.net安全性的限制,无法在客户端实现复杂的操作,比如磁盘空间操作和注册表操作。因为ActiveX控件是以本地用户的身份运行,可以突破.net安全性的限制,所以开发ActiveX控件还是很必要的。
C#写ActiveX控件的原理很简单,就是使用了.net平台和COM的互操作性。修改项目属性的目的就是将.net控件注册为com。这样,你就可以把这个控件完全当作ActiveX控件来对待了。比如,可以使用JS和VBS来调用,也可以使用C++来调用。
下面一步步来实现C#写ActiveX控件。
第一部分:用vs2008制作一个winForm控件
用vs2008建立一个新的“windows窗体控件库”命名为“WindowsFormsControlLibrary1”如下图
点击确定后,将UserControl1.cs更名为demo.cs。向界面里添加一个Labal、一个TextBox和一个Button,相应的修改控件属性。如下图:
为button1添加Click事件,代码如下:
private void button1_Click(object sender, EventArgs e)
{
label1.Text = textBox1.Text;
}
在AssemblyInfo.cs中引用System.Security命名空间,并添加一句:
[assembly : AllowPartiallyTrustedCallers()]
为类demo添加Attribute,[System.Runtime.InteropServices.Guid("A82F92E1-BA7F-3B32-B389-584E8AB4441F")]
好,现在编译整个工程,生成\bin\Debug\WindowsFormsControlLibrary1.dll,我们的winform控件就做好了。
下面在解决方案里添加一个web应用程序的工程,名为WebApplication1,用来测试我们的控件。
将WindowsFormsControlLibrary1.dll拷贝到WebApplication1所在的目录下。然后在Default.aspx 里面加入“<object id="helloworld" classid='http://localhost:59639/WindowsFormsControlLibrary1.dll#WindowsFormsControlLibrary1.demo' width="184" height="96" >
</object>
ok,编译运行后你将看到如下界面:
第二部分:把这个winForm控件转换为ActiveX控件
到目前为止,我们所实现的只是winform控件,还不是真正的ActiveX控件。
鼠标右键,打开WindowsFormsControlLibrary1的工程属性,在“应用程序”里点击“程序集信息…”显示如下界面:
选中“使程序集COM可见”,然后确定。
进入“生成”页面,如下图:
选中“为COM互操作注册”。
重新编译工程,这时WindowsFormsControlLibrary1.dll就变成了一个ActiveX控件。
如果编译时,提示你权限不够(Windows 7 UAC),需要以管理员运行Visual Studio。
如果编译时,The assembly could not be converted to a type library. Type library exporter
encountered an error while processing 'xxxxxx'.
Error: 找不到元素. 你在Relase 下进行编译。编译成功后,可以在注册表项HKEY_CLASSES_ROOT\WindowsFormsControlLibrary1.Demo
我们使用 工具—〉OLE/COM对象查看器查看,如图:
WindowsFormsControlLibrary1.demo已经被正确识别为COM组件。现在,我们已经可以像使用其它ActiveX控件一样在 网页中显示了。在WindowsFormsControlLibrary1.demo点击鼠标右键,选择Copy HTML <object> Tag to Clipboard,可以将代码拷入剪贴板。
我们在 Default.aspx 中粘贴剪贴板的内容,如下:
<object id="helloworld" classid="clsid:A82F92E1-BA7F-3B32-B389-584E8AB4441F" width="184">
</object>
编译运行整个工程,我们会在网页中看到之前的内容。好,现在我们的控件已经是货真价实的ActiveX控件了。
第三部分:实现ActiveX控件与网页的交互
我们在Demo中加入s1属性:
private string _s1;
public string s1
{
get
{
return _s1;
}
set
{
_s1 = value;
}
}
我们在Demo中加入ShowMessage方法:
public void showMessage()
{
MessageBox.Show(_s1);
}
修改Default.aspx 中的内容:
<object id="helloworld" classid="clsid:A82F92E1-BA7F-3B32-B389-584E8AB4441F"
width="184">
<param name="s1" value="用param传递控件属性"/>
</object>
<input type=’button' onclick=’helloworld.ShowMessage()' value=’用param传递控件属性’/>
<input type=’button' onclick=’helloworld.s1="用js和控件交互"; helloworld.ShowMessage()' value=’用js和控件交互’/>
好,编译运行整个工程,显示如下:
点击单击“用js和控件交互”按钮,应该可以实现交互了。
但是结果却很遗憾,我们发现IE跳出了对话框,如图所示
这时我们通过修改IE安全属性“对没有标记为安全的ActiveX控件进行初始化和运行”可以绕过这个问题,但是要真正解决需要实现IObjectSafety接口,把ActiveX控件标记为安全的ActiveX控件。
首先在工程里添加一个接口,命名为IObjectSafety.cs,代码如下:
using System;
using System.Runtime.InteropServices;
namespace WindowsFormsControlLibrary1
{
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
void GetInterfacceSafyOptions( System.Int32 riid,out System.Int32 pdwSupportedOptions, out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions( System.Int32 riid, System.Int32 dwOptionsSetMask, System.Int32 dwEnabledOptions);
}
}
注意添加命名空间“using System.Runtime.InteropServices”,Guid一定不能搞错。
然后在demo类里添加继承,如下:
public partial class demo : UserControl, WindowsFormsControlLibrary1.IObjectSafety
{…}
最后在demo类里实现两个特定方法:
public void GetInterfacceSafyOptions(Int32 riid, out Int32 pdwSupportedOptions, out Int32 pdwEnabledOptions)
{
// TODO: 添加 WebCamControl.GetInterfacceSafyOptions 实现
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
}
public void SetInterfaceSafetyOptions(Int32 riid, Int32 dwOptionsSetMask, Int32 dwEnabledOptions)
{
// TODO: 添加 WebCamControl.SetInterfaceSafetyOptions 实现
}
重新编译,然后将IE里面的设置改回来。现在,我们发现,和JS的交互已经没有问题了。
在前面我们已经完成了ActiveX控件的开发,接下来的就是发布它了。
第四部分:制作安装包
在解决方案了添加一个“安装”项目,命名为SetupActiveX。
在项目的“应用程序文件夹”里添加“主输出项目”WindowsFormsControlLibrary1
将主输出项目”WindowsFormsControlLibrary1的Register属性改为vsdrpCOM.如图:
现在我们生成安装程序,并把相应得程序拷贝到正确的目录中(本例中为默认网站目录下的跟文件夹中)。
现在我们又要重新改动Default.aspx 文件了。修改后的结果如下:
<div>
<object id="helloworld" classid="clsid:A82F92E1-BA7F-3B32-B389-584E8AB4441F"
width="184"
codebase="Setup.exe">
<param name="s1" value="用param传递控件属性"/>
</object>
<input type=’button' onclick=’helloworld.ShowMessage()' value=’用param传递控件属性’/>
<input type=’button' onclick=’helloworld.s1="用js和控件交互"; helloworld.ShowMessage()' value=’用js和控件交互’/>
</div>
注意,我们在object块中加入了codebase属性,这就是制定的下载控件的位置,可以使用相对路径。
但是,我们现在还不能正确请求这个页面,因为我们还没有对我们的控件进行签名。为了绕过这个问题,我们可以修改IE的安全属性"对没有标记为安全的ActiveX控件进行初始化和脚本运行"和"下载未签名的ActiveX控件"。
第五部分:给安装包签名
对于 Internet 应用程序的开发人员和用户而言,代码安全是一个主要问题。有下列风险:恶意的代码、被篡改的代码和来自未知站点或作者的代码。
Internet 开发时有两种保证安全的基本方法。第一种方法称为“沙箱”。在此方法中,应用程序只能访问一组特定的API,并且被从潜在危险的 API(如文件 I/O,程序可能在此毁坏用户计算机中的数据)中排除。第二种方法使用数字签名来实现。此方法对 Internet 称为“收缩包装”。使用私匙/公匙技术验证和签名代码。在代码运行之前,验证其数字签名,确保该代码的来源是已知的并且经过验证,并且自签名后该代码未被 更改过。
在第一种情形中,信任应用程序不会有任何损害,并且信任该应用程序的来源。在第二种情形中,使用数字签名来验证真伪。数字签名是用于识别和提供关于代码发行者的详细资料的工业标准。其技术基于标准,包括 RSA 和 X.509。浏览器一般允许用户选择是否希望下载并运行来源未知的代码。
给文件签名首先要获得软件发行证书。为此,必须向证书颁发机构提出请求(比如微软或其他认证代理机构)。在申请期间,必须生成一个密匙对并向证书颁发机构提供标识信息(如名字、地址和公匙)。还必须作出在法律上具有约束力的保证,即保证您不能也不会分发您知道或本应知道含有病毒或将以其他方式恶意损害用户的计算机或代码的软件。当然,这种认证是收费的,一般在2——8KRMB不等。
这里,我们使用Microsoft.Net带的MAKECERT和CERT2SPC实用工具生成测试的软件发行证书。然后用这个测试证书通过 SignTool工具为我们的发行包签名,当然,这对软件发行是无效的,也就是说在Internet环境下还是需要修改IE安全设置才可以下载安装。但是在局域网环境下可以实现直接下载安装,仅可用于测试代码签名。
MAKECERT.exe、CERT2SPC.exe和SignTool.exe三个工具在C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin 目录下。你可以通过vs2008的“Visual Studio 2008 Command Prompt” 进入命令行状态,这时系统会自动加载对应的Path参数,你在任何一个目录下都可以直接运行着三个小工具了。
1、用MAKECERT.exe创建用于数字签名的公钥和私钥对
在命令行下输入“makecert -ss lwchome -n "CN=lwchome CRD公司" -sv d:\test\lwchomecert.pvk -r d:\test\wchomecert.cer”
其中ss-主题的证书存储名称, n-证书颁发对象,此名称必须符合 X.500 标准。最简单的方法是在双引号中指定此名称,并加上前缀 CN=;例如,"CN=myName"。注意这里的CN必须大写。-r-证书存储位置,-sv 导出私钥文件(为了签名使用)。注意:这个时候会让输入三次密码,三次要完全一致。
2、用Cert2Spc.exe生成spc发行者证书:cert2spc d:\test\lwchomecert.cer d:\test\lwchomecert.spc
3、用SignTool.exe对安装包数字签名
在命令行下输入“signtool signwizard”,会弹出签名工具界面如下:
点击下一步,输入安装包的位置:
点击下一步,选择“自定义”
点击下一步,从文件选择:
选择刚刚制作的证书d:\test\lwchomecert.spc,点击下一步:
选择磁盘上的私密钥文件,选中刚刚生成的私密钥d:\test\lwchomecert.pvk ,然后点击下一步,输入刚刚的密码显示如下界面:
选择md5,点击下一步:
此页无需修改,直接点击下一步:
输入描述和web位置,点击下一步:
添加时间戳http://timestamp.verisign.com/scripts/timstamp.dll,点击下一步:
完成输入刚刚的密码即可。
这时,鼠标右击安装包文件“setup.exe”,可以查看数字签名信息:
如果是正式发行,请从微软或代理机构申请正式证书和密钥,然后用signtool工具加密你的发行包即可。
第六部分:部署
将签名的setup.exe拷贝到网站目录下,替换之前没有签名的安装包。用iis发布网站,注意“执行权限选择纯脚本”