原来写过一篇文章:C#开发ActiveX控件及制作CAB包,关注的人很多,后来一直比较忙,没有及时解决大家提出的问题,这几天总结一下。
这篇文章说明如何编写ActiveX控件并制作CAB压缩包。制作一个ActiveX控件,在网页中安装加载,然后可以通过javascript访问,设置ActiveX控件中的时间显示。
1、开发及测试环境:
(1)开发环境:
????????? Visual Studio 2008 SP1
?????????? cabsdk(下载地址:http://support.microsoft.com/kb/310618)
(2)测试环境:
????????? Windows Server 2003 R2 SP2
????????? IE6
2、创建项目
我这里创建了三个项目:
(1)HelloBossma :
项目模板:Windows窗体控件库
(2)HelloBossmaSetup:
项目模板:安装项目?
(3)Web:
项目模板:ASP.NET 网站
3、HelloBossma项目
这个项目用于编写具体的控件,并生成安装文件所需要的dll。
(1)添加用户控件:
(2)设计控件:
添加Panel、GroupBox、Label 控件。NowTime是一个Label控件,用于显示时间。
然后在控件对应的代码文件中编写程序:
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 HelloBossma { ??? /// <summary> ??? /// Guid将用作控件的classid ??? /// IObjectSafety的是用来标记可安全执行脚本的ActiveX控件 ??? /// </summary> ??? [Guid("636B8CE1-7512-464C-B63C-FC75BDCA21DB"), ProgId("HelloBossma.HelloBossmaActiveX"), ComVisible(true)] ??? public partial class HelloBossmaActiveX : 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 HelloBossmaActiveX() ??????? { ??????????? InitializeComponent(); ??????? } ??????? /// <summary> ??????? /// 设置当前时间 ??????? /// </summary> ??????? /// <param name="timeStr"></param> ??????? public void SetTime(string timeStr) ??????? { ??????????? this.label2.Text = timeStr; ??????? } ??????? 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; ??????? } ??? } }
关于IObjectSafety的实现参考了:http://www.pinvoke.net/default.aspx/Interfaces/IObjectSafety.html
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace HelloBossma { ??? [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); ??? } }
这里还包含了一个可以被外部调用的方法,传进来一个字符参数,并显示出来:
/// <summary> ??????? /// 设置当前时间 ??????? /// </summary> ??????? /// <param name="timeStr"></param> ??????? public void SetTime(string timeStr) ??????? { ??????????? this.label2.Text = timeStr; ??????? }
(3)设置生成属性,勾选:为Com互操作注册
(4)生成项目,生成这两个文件:
HelloBossma.dll
HelloBossma.tlb
是必须的,否则生成不成功。
4、HelloBossmaSetup项目
这是一个安装项目,用来生成安装程序。
(1)在项目上点右键,【添加】->【项目输出】,选择上边的HelloBossma项目
(2)在安装项目上点右键,属性
安装URL:貌似用于查找应用程序更新,具体看:http://msdn.microsoft.com/zh-cn/library/c37e68bc(VS.90).aspx
这个目录最好是实际存在的,用来存放生成的安装文件,供客户端下载安装。没有的话就随便输入一个吧。
(3)添加卸载程序
拷贝文件C:\Windows\System32\msiexec.exe文件,修改文件名为Uninstall.exe,添加到安装项目中,然后创建一个快捷方式。
在【用户的“程序”菜单下边】添加一个文件夹HelloBossma,将快捷方式拖动到这里边。
在卸载控件上点击右键,属性:
设置Arguments,就是指定要卸载的程序,后面的ProductCode可以这样获得:
选中项目,然后鼠标放到右侧的“属性”上,就可以看到ProductCode了:
(4)最后生成项目
5、制作CAB文件
(1)为了方便操作,可以将CABARC.EXE添加到环境变量中:桌面上右击“我的电脑”,“属性”,“高级”,“环境变量”,“系统变量”,找到“Path”,在后边把CABARC.EXE所在的路径添加上去,注意用分号隔开新添加的路径。
(2)准备好文件
install.inf :CAB安装配置文件
HelloBossmaSetup.msi:安装程序文件
install.inf文件的内容:
[version] signature="$CHICAGO$" AdvancedINF=2.0 [Setup Hooks] hook1=hook1 [hook1] run=msiexec.exe /i "%EXTRACT_DIR%\HelloBossmaSetup.msi" /qn
run:一般只需要修改这个就行了
(3)执行cabarc命令
桌面左下角“开始”,“运行”,输入cmd,打开命令提示符工具,进入准备好的文件的目录,执行命令:
cabarc n HelloBossma.cab HelloBossmaSetup.msi install.inf?
显示“Completed successfully” ,打开所在目录,就可以看到生成的文件了。
6、部署到网站
在网站中新建一个目录hellobossma,将生成的cab文件拷贝到里边。
新建一个网页,将控件添加到页面:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> ??? <title></title> ??? <script type="text/javascript"> ??????? function SetTime() { ??????????? var d = new Date(); ??????????? var vYear = d.getFullYear(); ??????????? var vMon = d.getMonth() + 1; ??????????? var vDay = d.getDate(); ??????????? var vHour = d.getHours(); ??????????? var vMin = d.getMinutes(); ??????????? var vSec = d.getSeconds(); ??????????? document.HelloBossma.SetTime(vYear + "-" + vMon + "-" + vDay + " " + vHour + ":" + vMin + ":" + vSec) ??????? } ??? </script> </head> <body style="font-size: 12px; color: black"> ??? <form id="form1" runat="server"> ??? <div> ??????? <object classid="clsid:636B8CE1-7512-464C-B63C-FC75BDCA21DB" codebase="hellobossma/HelloBossma.CAB" width="442" height="87" id="HelloBossma" name="HelloBossma"> ??????? </object> ??????? <br /> ??????? <br /> ??????? <input type="button" value="显示当前时间" onclick="SetTime()" /> ??? </div> ??? </form> </body> </html>
ActiveX控件作为一个object添加到页面中,其classid是在编写HelloBossmaActiveX类时定义好的Guid值,codebase用来指示cab安装文件的路径,还可以设置宽度、高度。另外其中文字受页面中字体样式的影响。
因为我们的ActiveX控件没有签名,所以将测试站点加到“本地Intranet”中或者“可信站点”中,并设置安全级别为“低”。
然后打开浏览器,提示安装,点击“安装”,稍等下,效果就出来了:
点击按钮,就可以通过javascript设置ActiveX控件中的时间了。
Over!
这篇文章是一个简单的例子,没有进行更广范围平台的测试,后续文章会逐渐加入。
刚入手开发这个… 照葫芦画瓢 , .例子很好.值得学习
在添加卸载程序的时候一直托不进去,发现弄错了,楼主写的比较简单,但是还是很感谢!!!!!
发表评论
相关文章
国内AI资源汇总,AI聊天、AI绘画、AI写作、AI视频、AI设计、AI编程、AI音乐等,国内顺畅访问,无需科学上网。
扫码或点击进入:萤火AI大全
文章分类
最新评论