ActiveX接口 是一個開放的集成平台,為開發人員、用戶和 Web生產商提供了一個快速而簡便的在 Internet 和 Intranet 創建程序集成和內容的方法。 使用 ActiveX, 可輕松方便的在 Web頁中插入 多媒體效果、 交互式對象、以及復雜程序,創建用戶體驗相當的高質量多媒體 CD-ROM 。
簡單的說,用activeX和js差不多,但是有些是js無法實現的,這個時候就可以考慮一下activeX,一般要求是在客戶端執行的程序,比如對本機的串口操作等,而服務器端不用做任何的操作和加載任何的插件,下面來簡單介紹下如何用C#自己封裝一個activeX組件,並在web中應用。
說明:我的這個例子是在實際工作中,需要把第三方廠家的C/S端動態庫,封裝為B/S端動態庫。如果您的動態庫不調用第三方廠家的動態庫,可以在接口中去除鏈接即可。
開發工具:VisualStudio2012 (VisualStudio2017在添加用戶控件后,自動生成匹配的程序代碼集,故不推薦!)
步驟一:搭建開發環境
說明:選擇類庫,編輯好名稱和路徑位置。
步驟二: 更改“項目屬性-應用程序-程序集信息”設置,勾選“使程序集 COM 可見”
說明:勾選COM有2處,都需要勾選
第一處:
第二處:
步驟三: 修改AssemblyInfo.cs文件,添加[assembly: AllowPartiallyTrustedCallers()]項(需要引用System.Security名稱空間)
步驟三: 添加一個Windows用戶控件
步驟四:防止瀏覽器一直彈出安全警告
為了提高程序的安全性,以便在客戶端安裝的時候在瀏覽器提高信任度,我們需要實現接口IObjectSafety

1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Runtime.InteropServices; 5 6 namespace mProjectName 7 { 8 [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")] 9 [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] 10 public interface IObjectSafety 11 { 12 [PreserveSig] 13 int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); 14 15 [PreserveSig()] 16 int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions); 17 } 18 }
該類只是一個接口而已,我們還需要在自己的接口中去實現具體的方法。具體放置位置如下
提示:這部分代碼都是通用的,不必做任何修改。
步驟五:用戶控件的編寫
首先,用戶控件的設計部分:XXX.Designer.cs的模塊,最好需要弄點圖片或者文字加載到上面去,一邊用瀏覽器加載的時候方便判斷是否加載成功。
其次,編寫主接口模塊:
首先,第一個接口 ItfLyCnIcObject是用來給家口注冊后,提供函數名稱的,您可以用這個函數實現不懂的功能,當然接口的函數還沒有實現的,是在下面的XXX_BObject 接口里面實現的。
ItfLyCnIcObject接口代碼示例:
主體XXXIc_Object接口代碼示例:
主體XXXIc_Object接口代碼分為3部分,函數定義是為了加載第三方廠家的接口路徑和方法,以及參數等,IObjectSafety接口是通用的,實現之前的IObjectSafety接口方法的具體實現,下面的具體方法是實現 ItfLyCnIcObject接口中方法的具體實現
IObjectSafety接口方法是公用的,無需修改:

1 private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"; 2 private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}"; 3 private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}"; 4 private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}"; 5 private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; 6 7 private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001; 8 private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002; 9 private const int S_OK = 0; 10 private const int E_FAIL = unchecked((int)0x80004005); 11 private const int E_NOINTERFACE = unchecked((int)0x80004002); 12 13 private bool _fSafeForScripting = true; 14 private bool _fSafeForInitializing = true; 15 16 17 public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions) 18 { 19 int Rslt = E_FAIL; 20 21 string strGUID = riid.ToString("B"); 22 pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; 23 switch (strGUID) 24 { 25 case _IID_IDispatch: 26 case _IID_IDispatchEx: 27 Rslt = S_OK; 28 pdwEnabledOptions = 0; 29 if (_fSafeForScripting == true) 30 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; 31 break; 32 case _IID_IPersistStorage: 33 case _IID_IPersistStream: 34 case _IID_IPersistPropertyBag: 35 Rslt = S_OK; 36 pdwEnabledOptions = 0; 37 if (_fSafeForInitializing == true) 38 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA; 39 break; 40 default: 41 Rslt = E_NOINTERFACE; 42 break; 43 } 44 45 return Rslt; 46 } 47 48 public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) 49 { 50 int Rslt = E_FAIL; 51 52 string strGUID = riid.ToString("B"); 53 switch (strGUID) 54 { 55 case _IID_IDispatch: 56 case _IID_IDispatchEx: 57 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && 58 (_fSafeForScripting == true)) 59 Rslt = S_OK; 60 break; 61 case _IID_IPersistStorage: 62 case _IID_IPersistStream: 63 case _IID_IPersistPropertyBag: 64 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && 65 (_fSafeForInitializing == true)) 66 Rslt = S_OK; 67 break; 68 default: 69 Rslt = E_NOINTERFACE; 70 break; 71 } 72 73 return Rslt; 74 }
ItfLyCnIcObject中的方法實現中的方法名稱和具體參數,以及個數都必須一致
之后,再從新生成無誤后,會在bin文件的Debug文件中生成你封裝好的dll
步驟六:注冊該接口
這個得到的dll要和第三方廠家的dll放到一起(就是我們之前圖片中的哪個第三方廠家的DLL),一並放到C:\Windows\SYSWOW64目錄下,因為我的是windows64位電腦,如果你的電腦是32位的,一般放置到C:\Windows\System32目錄下。
之后打開CMD,寫入一下注冊字符:
"C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" /codebase C:\Windows\SysWOW64\XXXXc_B.dll
具體截圖如下:
然后回車即可注冊成功。(中間可能有警告,不用管,只要有注冊成功字樣即可)
步驟七:接口的唯一ClassID查看
這個ClassID就是瀏覽器識別該該接口的唯一憑證,也就是說有了這個ClassID,一台電腦原則上可以注冊無數的這種接口。可以通過接口查看器查看
我用的查看工具是oleview,大家可以用其他的看看,一般只要是正確的注冊,都可以看到接口名稱,如果沒有看到,怎么能夠接口沒有注冊成功。
步驟八:調用接口
新建一個html頁面,添加下面的代碼
具體代碼分析:
到此,就基本上結束了,頁面可以用JS來調用了,另外,瀏覽器的安全設置大家最好按網上其他大神說的那樣設置就好。
由於這個是實際項目中的上線代碼,故,內容可以不能全部公開,部分關鍵字段也做了刷白處理,可能對您觀看造成不便,請多多包涵。如果大家有興趣或者疑問,歡迎大家把疑問發送到我的郵箱1732182169@qq.com,或者直接QQ:1732182169聯系我,大家一起學習探討!
另外可以參考下面這位大神寫的,也很不錯:http://www.cnblogs.com/shuang121/archive/2012/06/04/2534296.html