開發環境:VS2008javascript
第一步 建立項目html
新建一個項目,選擇「Windows窗體控件庫」,建立一個用戶控件項目「ActiveXDemo」(注意,這裏起名不能用中文,不然後面會出問題),裏面有個用戶控件類UserControl1.csjava
在類中寫上你本身須要的業務邏輯代碼,保存瀏覽器
第二步 設置項目屬性安全
在AssemblyInfo.cs裏添加[assembly: AllowPartiallyTrustedCallers()],須要引用using System.Security;命名空間函數
設置項目屬性,右鍵項目——屬性工具
選擇「應用程序」,點開「程序集信息」ui
勾選「使程序集COM可見」,點「肯定」spa
而後選擇「生成」,滾動拉倒底部,勾選「爲COM互操做註冊」插件
而後保存,從新編譯項目,至此,此時的「ActiveXDemo.dll」就成了一個ActiveX控件
第三步 安裝外部工具
安裝外部工具「OLE/COM對象查看器」和「建立GUID」(已有這兩款工具的能夠忽略此步驟)
1.OLE/COM對象查看器
這款工具是用來查看ActiveX控件的,也就是驗證你的項目有沒有成爲一個ActiveX控件
安裝方法:點開VS頂部菜單欄「工具」——「外部工具」
而後,添加一個「OLE/COM對象查看器」,對應的命令程序通常放在C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\OleView.Exe
點擊「應用」,「肯定」,這就算是安裝完成,再從新點開頂部的「工具」菜單看看,裏面就有一項「OLE/COM對象查看器」
點擊「OLE/COM對象查看器」,展開左側的「.NET Category」
你會發現,這裏面就有你剛剛建立的ActiveX控件
這就是OLE/COM對象查看器的做用
2.建立GUID
高版本的VS貌似都自帶了這個工具,可是在有的低版本或者安裝不完整好比Vs2008中不必定有這個工具,因此在沒有的時候須要安裝一下
安裝方法同上,只不過命令程序的地址通常是C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\Tools\guidgen.exe
此工具的用途在下面的步驟中會講到
第四步 提升ActiveX插件的安全等級
IE怎麼知道一個插件是腳本安全的?它是經過如下兩個辦法。
一是查詢ActiveX組件是否實現了IObjectSafety接口,而且返回腳本安全;
二是查詢ActiveX組件是否在註冊表的Component Category Manager裏代表本身實現了CATID_SafeForInitializing和CATID_SafeForScripting。
這裏咱們只說第一種實現IObjectSafety接口
首先,爲控件類UserControl1添加一個GUID,這個編號將用於B/S系統的客戶端調用時使用(可使用 工具-建立GUID 菜單建立一個GUID):
using System; using System.Collections.Generic; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; namespace ActiveXDemo { [Guid("BB725724-65D6-4e71-AA11-DEDFAFE9248F"), ProgId("ActiveXDemo.UserControl1"), ComVisible(true)] public partial class UserControl1 : UserControl,IObjectSafety {
注意,要引入System.Runtime.InteropServices;命名空間
其次,爲了讓ActiveX控件得到客戶端的信任,控件類還須要實現一個名爲「IObjectSafety」的接口,所以在項目中添加一個接口類IObjectSafety
直接將下列代碼複製粘貼,不要做任何改動,尤爲是GUID,都是固定的,不能改
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ActiveXDemo { [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); } }
一樣,須要引入System.Runtime.InteropServices;命名空間
接着,在控件類UserControl1中實現IObjectSafety的接口
#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 = 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 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; } #endregion
這些代碼也是固定的,不能改動,直接複製粘貼就好了
第五步 製做成安裝文件
在原項目解決方案中新建一個安裝項目,在VS2008中,是這樣操做的
新建項目——其餘項目類型——安裝和部署——安裝項目
注意,這裏下方「解決方案」這裏要選擇「添入解決方案」
而後,右鍵安裝項目——添加——項目輸出
將咱們的項目ActiveXDemo設爲主輸出
點肯定,而後在主輸出文件上右鍵——屬性
將Register屬性設爲vsdrpCOM
從新編譯安裝項目,打開安裝項目所在目錄
至此,ActiveX瀏覽器插件的安裝包就製做好了,雙擊setup.exe文件或ActiveXDemoSetup.msi文件能夠將瀏覽器插件安裝到你的電腦
第六步 使用ActiveX插件
新建一個Web項目或者一個Html文件,在須要使用瀏覽器插件的頁面上加入如下代碼:
<html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title>無標題頁</title> </head> <body> <object id="csharpActiveX" classid="clsid:BB725724-65D6-4e71-AA11-DEDFAFE9248F" width="100%" height="150"></object> <form id="form1" runat="server"> <div> <input type='button' onclick='csharpActiveX.Test()' value='我是按鈕'/> </div> </form> </body>
其中,重點是object標籤裏的classid屬性,屬性裏面的GUID對應的就是第四步中指定的GUID
直接使用object定義的id屬性就能夠調用UserControl1類中的方法,是否是很方便?
爲了更方便直觀的看出插件有沒有正常加載,能夠再加入一些檢測代碼,以下:
<body> <object id="csharpActiveX" classid="clsid:BB725724-65D6-4e71-AA11-DEDFAFE9248F" width="100%" height="150"></object> <form id="form1" runat="server"> <div> <input type='button' onclick='csharpActiveX.Test()' value='我是按鈕'/> </div> </form> </body> <script type="text/javascript"> var objCard = document.getElementById("csharpActiveX"); if (objCard.object==null) { alert("csharpActiveX插件未安裝!"); } else{ alert("已檢測到csharpActiveX插件!"); } </script> </html>
而後,因爲只有IE支持ActiveX瀏覽器插件,因此在IE瀏覽器中打開這個頁面,看一下效果
這時,不放心的話,能夠再檢查我們的ActiveX插件究竟有沒有安裝上
點開工具欄「工具」——「管理加載項」
能夠看到其中有一項ActiveXDemo.UserControl1,這就是咱們安裝上去的瀏覽器插件
第七步 ActiveX插件調用頁面Js
這裏,主要須要引入一個程序集叫Microsoft.mshtml.dll,它在系統文件夾裏C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies
引入後,開始在插件項目裏寫上註冊Js函數相關的代碼,以下
private IHTMLWindow2 temphtml = null; private string functionstr = ""; public void RegJs(object objWinJs, string funcJs) { temphtml = (IHTMLWindow2)objWinJs; if (temphtml != null && !string.IsNullOrEmpty(funcJs)) { functionstr = funcJs; } else { temphtml = null; functionstr = ""; MessageBox.Show("註冊ActiveX插件回調腳本失敗"); } }
以及,執行頁面Js函數的代碼
private void ShowResult(object s, EventArgs e) { try { //必需要阻塞線程一段時間,以避免在交易超時的狀況下,因爲read太快致使讀取不完整 System.Threading.Thread.Sleep(500); string txt = serialPort.ReadExisting(); temphtml.execScript("var msgActiveX='" + txt+"';", "JScript"); temphtml.execScript(functionstr + "()", "JScript"); } catch (Exception ex) { MessageBox.Show(ex.Message.ToString()); } }
在這裏,我向頁面輸出了一個msgActiveX變量,並調用了前面註冊過的Js函數
而後,咱們還須要在頁面加載的時候,調用插件的註冊JS函數方法,以及此Js函數定義
<script type="text/javascript"> Ext.onReady( function() { objCard.regJs(window, 'test'); } );
function test() {
var str = msgActiveX.substring(5);
var objJson = eval('(' + str + ')');
alert(objJson.responseCode);
//alert("回調函數執行成功");
} </script>
至此,恭喜你已成功掌握了製做ActiveX瀏覽器插件的技能~