ActiveX控件以前也叫做OLE控件,它是微軟IE支持的一種軟件組件或?qū)ο,可以將其插入到Web頁(yè)面中,實(shí)現(xiàn)在瀏覽器端執(zhí)行動(dòng)態(tài)程序功能,以增強(qiáng)瀏覽器端的動(dòng)態(tài)處理能力。通常ActiveX控件都是用C++或VB語(yǔ)言開(kāi)發(fā),本文介紹另一種方式,在.NET Framework平臺(tái)上,使用C#語(yǔ)言開(kāi)發(fā)ActiveX控件。
雖然本文通篇都在講如何使用C#語(yǔ)言開(kāi)發(fā)ActiveX控件,但我并不極力推薦使用這種技術(shù),因?yàn)樵摷夹g(shù)存在明顯的局限,即需要瀏覽器端安裝.NET Framework(版本取決于開(kāi)發(fā)ActiveX控件使用的.NET Framework版本),該局限對(duì)于挑剔的互聯(lián)網(wǎng)用戶,幾乎是不可接受的。所以,我建議以下幾條均滿足時(shí),方可考慮使用該技術(shù):
開(kāi)發(fā)團(tuán)隊(duì)中沒(méi)有人掌握使用C++/VB開(kāi)發(fā)ActiveX控件技術(shù);
該ActiveX控件不用于互聯(lián)網(wǎng);
用戶對(duì)僅能使用IE瀏覽器訪問(wèn)表示可以接受;
用戶對(duì)在瀏覽器端安裝.NET Framework組件表示可以接受。
另外,我建議如果不是因?yàn)榭丶囊蕾噹?kù)基于更高版本的.NET Framework,或需要更高版本的.NET Framework提供的擴(kuò)展功能(如需要WCF等),盡量在.NET Framework 2.0上開(kāi)發(fā)ActiveX控件,因?yàn)?NET Framework 2.0只有20M,相比300M的.NET Framework 3.5和40M的.NET Framework 4.0都要小很多,對(duì)客戶端操作系統(tǒng)的要求也要低很多,并且隨著Windows版本的不斷升級(jí)換代,Windows Vista以后的版本已經(jīng)內(nèi)置了.NET Framework 2.0。等到Windows XP系統(tǒng)壽終正寢之時(shí),也將迎來(lái)該技術(shù)的春天。所以,別被我上面的建議夯退了,掌握該技術(shù)其實(shí)還是蠻有實(shí)用價(jià)值的,畢竟,C#高效的開(kāi)發(fā)效率很有吸引力。
本文接下來(lái)將使用C#語(yǔ)言開(kāi)發(fā)一個(gè)ActiveX控件,實(shí)現(xiàn)對(duì)瀏覽器端的MAC地址遍歷功能;另外,提供一個(gè)在Web靜態(tài)頁(yè)面中調(diào)用該控件的測(cè)試實(shí)例。本實(shí)例的開(kāi)發(fā)環(huán)境為Visual Studio 2010旗艦版(SP1),目標(biāo)框架為.NET Framework 2.0;瀏覽器端測(cè)試環(huán)境為Windows 7旗艦版,IE8。
控件開(kāi)發(fā)
使用C#進(jìn)行ActiveX控件開(kāi)發(fā)過(guò)程其實(shí)很簡(jiǎn)單。首先,在解決方案中添加一個(gè)類庫(kù)項(xiàng)目,目標(biāo)框架使用.NET Framework 2.0,如圖1所示:
圖1創(chuàng)建ActiveX控件類庫(kù)
此處有一個(gè)關(guān)鍵操作,需要設(shè)置類庫(kù)項(xiàng)目屬性->程序集信息->使程序集COM可見(jiàn),如圖2所示:
圖2設(shè)置ActiveX控件類庫(kù)程序集COM可見(jiàn)
ActiveX類庫(kù)的內(nèi)容大致包括兩部分,IObjectSafety接口和實(shí)現(xiàn)該接口的控件類。考慮所有控件類都要實(shí)現(xiàn)IObjectSafety接口,可以將該接口的實(shí)現(xiàn)抽象為一個(gè)控件基類。
一、IObjectSafety接口
為了讓ActiveX控件獲得客戶端的信任,控件類還需要實(shí)現(xiàn)一個(gè)名為“IObjectSafety”的接口。先創(chuàng)建該接口(注意,不能修改該接口的GUID值),接口內(nèi)容如下:
1 [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")] 2 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 3 public interface IObjectSafety 4 { 5 [PreserveSig] 6 int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); 7 8 [PreserveSig()] 9 int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions); 10 }
二、ActiveXControl控件基類
1 public abstract class ActiveXControl : IObjectSafety 2 { 3 #region IObjectSafety 成員 4 5 private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}"; 6 private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}"; 7 private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}"; 8 private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}"; 9 private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; 10 11 private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001; 12 private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002; 13 private const int S_OK = 0; 14 private const int E_FAIL = unchecked((int)0x80004005); 15 private const int E_NOINTERFACE = unchecked((int)0x80004002); 16 17 private bool _fSafeForScripting = true; 18 private bool _fSafeForInitializing = true; 19 20 21 public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions) 22 { 23 int Rslt = E_FAIL; 24 25 string strGUID = riid.ToString("B"); 26 pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA; 27 switch (strGUID) 28 { 29 case _IID_IDispatch: 30 case _IID_IDispatchEx: 31 Rslt = S_OK; 32 pdwEnabledOptions = 0; 33 if (_fSafeForScripting == true) 34 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER; 35 break; 36 case _IID_IPersistStorage: 37 case _IID_IPersistStream: 38 case _IID_IPersistPropertyBag: 39 Rslt = S_OK; 40 pdwEnabledOptions = 0; 41 if (_fSafeForInitializing == true) 42 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA; 43 break; 44 default: 45 Rslt = E_NOINTERFACE; 46 break; 47 } 48 49 return Rslt; 50 } 51 52 public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions) 53 { 54 int Rslt = E_FAIL; 55 56 string strGUID = riid.ToString("B"); 57 switch (strGUID) 58 { 59 case _IID_IDispatch: 60 case _IID_IDispatchEx: 61 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && 62 (_fSafeForScripting == true)) 63 Rslt = S_OK; 64 break; 65 case _IID_IPersistStorage: 66 case _IID_IPersistStream: 67 case _IID_IPersistPropertyBag: 68 if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && 69 (_fSafeForInitializing == true)) 70 Rslt = S_OK; 71 break; 72 default: 73 Rslt = E_NOINTERFACE; 74 break; 75 } 76 77 return Rslt; 78 } 79 80 #endregion 81 }
三、MacActiveX控件類
1 [Guid("65D8E97F-D3E2-462A-B389-241D7C38C518")] 2 public class MacActiveX : ActiveXControl 3 { 4 public string GetMacAddress() 5 { 6 var mc = new ManagementClass("Win32_NetworkAdapterConfiguration"); 7 var mos = mc.GetInstances(); 8 var sb = new StringBuilder(); 9 10 foreach (ManagementObject mo in mos) 11 { 12 var macAddress = mo["MacAddress"]; 13 14 if (macAddress != null) 15 sb.AppendLine(macAddress.ToString()); 16 } 17 18 return sb.ToString(); 19 } 20 }
注意,第一行指定的Guid值即為該ActiveX控件的唯一標(biāo)識(shí),請(qǐng)保證其唯一性。Guid的生成有多種方法,你可以在系統(tǒng)目錄的Program Files目錄搜索一個(gè)名為guidgen.exe的工具,用該工具產(chǎn)生;也可以寫一段測(cè)試代碼,調(diào)用Guid.NewGuid()方法產(chǎn)生;有的Visual Studio版本也提供了快捷方式,在“工具->生成GUID”菜單下。另外,訪問(wèn)MAC需要添加對(duì)System.Management系統(tǒng)組件的引用。
到此,控件類庫(kù)的開(kāi)發(fā)工作就做完了,整個(gè)實(shí)現(xiàn)過(guò)程確實(shí)很簡(jiǎn)單。
發(fā)布
C#開(kāi)發(fā)的ActiveX控件類庫(kù)不像OCX那樣可以直接通過(guò)regsvr32.exe注冊(cè)(實(shí)際上,微軟提供了替工具regasm.exe,但由于這種方式要不能實(shí)現(xiàn)自動(dòng)升級(jí),所以本文就不介紹了),要使控件類庫(kù)運(yùn)行于瀏覽器端,可以采取兩種方式,一種是將控件類庫(kù)打包為MSI安裝包,然后直接在瀏覽器端安裝;另一種是將MSI再封裝為一個(gè)CAB包,這個(gè)CAB包就是一個(gè)ActiveX控件了,可以將它隨應(yīng)用程序一并發(fā)布,瀏覽器端訪問(wèn)包含有該控件的頁(yè)面時(shí),就會(huì)自動(dòng)提示安裝了。接下來(lái)就后一種發(fā)布方式進(jìn)行詳細(xì)講解。
一、安裝項(xiàng)目
在解決方案中添加一個(gè)安裝項(xiàng)目,如圖3所示:
圖3添加安裝項(xiàng)目
右鍵點(diǎn)擊新添加的安裝項(xiàng)目,依次選擇“添加->項(xiàng)目輸出”菜單,打開(kāi)添加項(xiàng)目輸出組對(duì)話框,并選擇ActiveX控件類庫(kù)“CSharpActiveX”作為主輸出,如圖4所示:
圖4添加項(xiàng)目輸出
雙擊安裝項(xiàng)目檢測(cè)到的依賴項(xiàng)“Microsoft .NET Framework”,打開(kāi)安裝項(xiàng)目的啟動(dòng)條件界面,選中“.NET Framework”項(xiàng),如圖5所示:
圖5安裝項(xiàng)目啟動(dòng)條件
按F4快捷鍵,打開(kāi)屬性窗口,設(shè)置.NET Framework項(xiàng)的Version為“.NET Framework 2.0”,如圖6所示:
圖6設(shè)置安裝項(xiàng)目的依賴框架
下面這步很關(guān)鍵,選中“主輸出來(lái)自CSharpActiveX(活動(dòng))”項(xiàng),如圖7所示:
圖7主輸出內(nèi)容項(xiàng)
設(shè)置主輸出項(xiàng)內(nèi)容的Register屬性值為vsdrpCOM,如圖8所示:
圖8設(shè)置主輸出項(xiàng)屬性
二、制作CAB包
Visual Studio 2010提供了CAB項(xiàng)目模板,但非常遺憾,無(wú)論我怎么設(shè)置,其生成的CAB安裝包都不能在終端成功安裝,最終只能放棄,轉(zhuǎn)而選擇了makecab.exe工具。源碼提供了該打包工具,位于CAB目錄下,共包含makecab.exe、cab.ddf、installer.inf和makecab.bat四個(gè)文件,其中cab.ddf和installer.inf文件需要簡(jiǎn)單說(shuō)明下。
cab.ddf文件定義了CAB文件的打包行為,內(nèi)容包括打包參數(shù),打包內(nèi)容項(xiàng)以及輸出文件等。需要指出的是,使用C#開(kāi)發(fā)的ActiveX控件CAB包中需要包含MSI文件和installer.inf安裝文件兩部分。cab.ddf文件內(nèi)容如下:
.OPTION EXPLICIT .Set Cabinet=on .Set Compress=on .Set MaxDiskSize=CDROM .Set ReservePerCabinetSize=6144 .Set DiskDirectoryTemplate="." .Set CompressionType=MSZIP .Set CompressionLevel=7 .Set CompressionMemory=21 .Set CabinetNameTemplate="CSharpActiveX.CAB" "installer.inf" "CSharpActiveX.msi"
installer.inf文件定義了CAB文件的安裝行為,作為控件的一部分打入CAB包中,其內(nèi)容如下:
[Setup Hooks] hook1=hook1 [hook1] run=msiexec /i %EXTRACT_DIR%\CSharpActiveX.msi /qn [Version] Signature= "$CHICAGO$" AdvancedInf=2.0
makecab.bat文件是調(diào)用makecab.exe進(jìn)行打包的批處理文件,內(nèi)容如下:
makecab.exe /f "cab.ddf"
當(dāng)生成安裝項(xiàng)目后,將CSharpActiveX.msi文件拷貝到CAB目錄下,就可以雙擊makecab.exe文件進(jìn)行打包了,執(zhí)行完成后會(huì)輸出CSharpActiveX.CAB文件,這就是所謂的ActiveX控件了。
三、簽名
IE采用了AuthentiCode代碼簽名技術(shù),對(duì)瀏覽器端安裝ActiveX控件行為進(jìn)行了控制。上面生成的ActiveX控件如果想在瀏覽器端成功安裝,需要對(duì)瀏覽器進(jìn)行設(shè)置,具體操作參見(jiàn)部署章節(jié)。
讓所有用戶都對(duì)IE進(jìn)行設(shè)置,顯得不太友好,為此,我們可以考慮使用AuthentiCode技術(shù)對(duì)ActiveX控件進(jìn)行簽名。Visual Studio 2010附帶的signtool.exe(以前版本的VS提供的是另一個(gè)工具signcode.exe)代碼簽名工具可以完成該工作(注意,并非一定要用微軟提供的工具進(jìn)行簽名,只要按照AuthentiCode技術(shù)標(biāo)準(zhǔn),使用 PKCS#7標(biāo)準(zhǔn)定義的數(shù)據(jù)結(jié)構(gòu)生成待簽名文件的數(shù)字簽名,并加入到待簽名文件的PE結(jié)構(gòu)中即可)。但需要先準(zhǔn)備一個(gè)PKCS#12(證書(shū)及私鑰)文件(.pfx),注意,該證書(shū)的增強(qiáng)型密鑰用法須包含代碼簽名這項(xiàng),如圖9所示:
圖9代碼簽名證書(shū)
本文源碼提供了一份測(cè)試PKCS#12文件Apollo.pfx,PIN碼為11111111。在Visual Studio命令提示(2010)中,進(jìn)入源碼的CAB目錄,輸入如下命令即可對(duì)ActiveX控件進(jìn)行簽名操作了:
signtool sign –f Apollo.pfx –p 11111111 CSharpActiveX.CAB
圖10對(duì)比了簽名前后的ActiveX控件文件屬性,可以看出,簽名后的ActiveX控件屬性中已經(jīng)多了一項(xiàng)數(shù)字簽名,表示該文件已經(jīng)過(guò)簽名。
圖10簽名前后的ActiveX控件屬性對(duì)比
出于方便考慮,本文源碼的CAB目錄下提供了一份signtool.exe工具的拷貝,這樣就可以將簽名命令加入makecab.bat文件中,修改后的makecab.bat我將其命名為makecabsigned.bat,內(nèi)容如下:
makecab.exe /f "cab.ddf" signtool sign -f Apollo.pfx -p 11111111 CSharpActiveX.CAB
應(yīng)用
ActiveX控件用于HTML靜態(tài)頁(yè)面,執(zhí)行于IE瀏覽器端。需要以
1 2 5 6 7 11 12
注意,
部署
ActiveX控件在IE瀏覽器端的部署會(huì)因ActiveX控件是否簽名而有所區(qū)別。下面就以此分類進(jìn)行說(shuō)明。當(dāng)然,首先需要將test.htm和CSharpActiveX.CAB文件部署到服務(wù)器上,假設(shè)部署后的訪問(wèn)地址為http://192.168.1.1/test.htm。
一、部署未簽名的ActiveX控件
未簽名的ActiveX控件不受瀏覽器端信任,默認(rèn)是不被允許安裝的。需要先將站點(diǎn)添加為可信站點(diǎn),具體步驟為:依次打開(kāi)IE“工具->Internet選項(xiàng)”,在“安全”選項(xiàng)卡中,選中“可信站點(diǎn)”,如圖11所示:
圖11 Internet安全選項(xiàng)
點(diǎn)擊“站點(diǎn)”按鈕,打開(kāi)可信站點(diǎn)管理對(duì)話框,將服務(wù)器站點(diǎn)添加到可信站點(diǎn)列表中,如圖12所示:
圖12可信站點(diǎn)對(duì)話框
回到“Internet選項(xiàng)”對(duì)話框,點(diǎn)擊“自定義級(jí)別”選項(xiàng)卡,打開(kāi)可信站點(diǎn)的安全設(shè)置對(duì)話框,如圖13所示:
圖13可信站點(diǎn)安全設(shè)置對(duì)話框
確認(rèn)“對(duì)未標(biāo)記為可安全執(zhí)行腳本的ActiveX控件初始化并執(zhí)行腳本”項(xiàng)設(shè)置為“啟用”,“下載未簽名的ActiveX控件”項(xiàng)設(shè)置為“提示”。
IE設(shè)置完成后,訪問(wèn)http://192.168.1.1/test.htm測(cè)試頁(yè)面(注意,Windows 7需要“以管理員身份運(yùn)行”IE方可成功安裝ActiveX控件),IE便會(huì)提示加載ActiveX控件,如圖14所示:
圖14首次訪問(wèn)提示加載ActiveX控件
點(diǎn)擊“為此計(jì)算機(jī)上的所有用戶安裝此加載項(xiàng)”,IE將彈出安全警告,確認(rèn)是否要安裝該ActiveX控件,如圖15所示:
圖15 ActiveX控件安裝安全警告
點(diǎn)擊“安裝”按鈕,確認(rèn)安裝該ActiveX控件,待IE狀態(tài)欄進(jìn)度條完成,說(shuō)明控件已安裝完成,可以通過(guò)查看“卸載或更改程序”項(xiàng)來(lái)確認(rèn)是否安裝成功,如圖16所示:
圖16確認(rèn)ActiveX控件成功安裝
我們可以從ActiveX控件安裝過(guò)程看出,瀏覽器端其實(shí)是以靜默安裝的方式完成對(duì)CAB包中的MSI安裝文件的安裝(有點(diǎn)拗口J)。安裝完成后,頁(yè)面成功調(diào)用ActiveX控件,彈出接口調(diào)用結(jié)果(注意Windows 7需要重啟IE,且不能用“以管理員身份運(yùn)行”方式啟動(dòng),否則會(huì)再次提示安裝ActiveX控件,但其實(shí)控件已經(jīng)成功安裝了,這個(gè)問(wèn)題很奇怪),效果如圖17所示:
圖17成功調(diào)用ActiveX控件接口
二、部署已簽名的ActiveX控件
因?yàn)镮E默認(rèn)允許安裝并運(yùn)行收信任的已簽名ActiveX控件,所以通過(guò)對(duì)ActiveX控件簽名,可以有效簡(jiǎn)化瀏覽器端的配置工作。你僅需要安裝簽名所用的證書(shū)及其證書(shū)鏈文件(本文源碼提供的簽名文件所含證書(shū)是自簽名證書(shū),所以它的證書(shū)鏈就只是它自己)。打開(kāi)源碼CAB目錄下的Apollo.cer(與Apollo.pfx文件對(duì)應(yīng)的數(shù)字證書(shū)文件)代碼簽名證書(shū)文件,如圖18所示:
圖18簽名證書(shū)文件
點(diǎn)擊“安裝證書(shū)”按鈕,將該證書(shū)安裝到“受信任的根證書(shū)頒發(fā)機(jī)構(gòu)”,如圖19所示:
圖19安裝代碼簽名證書(shū)
打開(kāi)IE的“工具->Internet選項(xiàng)”對(duì)話框,選擇“內(nèi)容”選項(xiàng)卡,點(diǎn)擊“證書(shū)”按鈕,打開(kāi)IE證書(shū)對(duì)話框,確認(rèn)在“受信任的根證書(shū)頒發(fā)機(jī)構(gòu)”選項(xiàng)卡中包含剛才導(dǎo)入的代碼簽名證書(shū),如圖20所示:
圖20成功導(dǎo)入代碼簽名證書(shū)
此時(shí),再訪問(wèn)測(cè)試頁(yè)面http://192.168.1.1/test.htm,IE就會(huì)提示安裝ActiveX控件了,而不再需要將站點(diǎn)添加到可信站點(diǎn)并設(shè)置IE選項(xiàng)了。
但是,如果用戶不能接受初次安裝需要導(dǎo)入代碼簽名證書(shū)及其證書(shū)鏈的方式,怎么辦呢?從圖20可以看到,Windows其實(shí)默認(rèn)內(nèi)置了一些權(quán)威的CA機(jī)構(gòu)證書(shū),可以向這些機(jī)構(gòu)申請(qǐng)一份代碼簽名證書(shū)及私鑰文件來(lái)對(duì)ActiveX控件簽名,這樣就可以避免該問(wèn)題了。但是,向權(quán)威的CA機(jī)構(gòu)申請(qǐng)證書(shū)是需要付費(fèi)的,所以需要權(quán)衡成本和易用性后,再做出選擇。
升級(jí)
要使C#編寫的ActiveX控件支持自動(dòng)升級(jí),需要做四件事情,即升級(jí)ActiveX控件庫(kù)版本、升級(jí)安裝項(xiàng)目版本、設(shè)置安裝項(xiàng)目注冊(cè)表項(xiàng)版本和升級(jí)網(wǎng)頁(yè)
一、升級(jí)ActiveX控件版本
打開(kāi)ActiveX控件項(xiàng)目的“程序集信息”對(duì)話框,升級(jí)程序集版本和文件版本,如圖21所示:
圖21升級(jí)ActiveX控件版本
二、升級(jí)安裝項(xiàng)目版本
選中安裝項(xiàng)目,按F4快捷鍵打開(kāi)安裝項(xiàng)目的屬性窗口,升級(jí)安裝項(xiàng)目的版本,如圖22所示:
圖22升級(jí)安裝項(xiàng)目版本
注意,此處還有一項(xiàng)關(guān)鍵工作要做,就是設(shè)置RemovePreviousVersions屬性值為True,這樣就會(huì)在升級(jí)時(shí)先自動(dòng)卸載之前版本的控件。
三、設(shè)置安裝項(xiàng)目注冊(cè)表項(xiàng)版本
瀏覽器端檢測(cè)ActiveX控件是否需要升級(jí),是通過(guò)比對(duì)
右鍵點(diǎn)擊安裝項(xiàng)目,依次選擇“視圖->注冊(cè)表”菜單,打開(kāi)安裝項(xiàng)目的注冊(cè)表編輯界面,并在HKEY_CLASSES_ROOT節(jié)點(diǎn)下,建立CLSID/{GUID}/InstalledVersion注冊(cè)表鍵路徑,如圖23所示:
圖23創(chuàng)建注冊(cè)表鍵路徑
右鍵點(diǎn)擊InstalledVersion鍵節(jié)點(diǎn),選擇“新建->字符串值”菜單,新建一個(gè)名稱為空(空名稱會(huì)顯示為“(默認(rèn)值)”),值為當(dāng)前控件版本號(hào)的鍵值,如圖24所示:
圖24添加InstalledVersion默認(rèn)鍵值
該步驟有幾個(gè)地方需要特別說(shuō)明。首先,{GUID}指的是ActiveX控件類的GUID,對(duì)應(yīng)本文MacActiveX類指定的GUID,且該項(xiàng)需要包括左右花括號(hào);其次,如果該安裝項(xiàng)目用于發(fā)布多個(gè)ActiveX控件(類),需要?jiǎng)?chuàng)建多個(gè){GUID}/InstalledVersion路徑;最后,InstalledVersion的默認(rèn)鍵值的主次版本號(hào)間是用“,”分隔,而不是“.”,后續(xù)升級(jí)時(shí),需要同步升級(jí)該鍵值版本號(hào)。
四、升級(jí)網(wǎng)頁(yè)
最后,需要升級(jí)網(wǎng)頁(yè)中的ActiveX對(duì)象引用版本號(hào),如下用下劃線標(biāo)識(shí)部分:
重新生成安裝程序,打CAB包,將升級(jí)的頁(yè)面及ActiveX控件(CAB包)更新到服務(wù)器。此時(shí),瀏覽器端重新訪問(wèn)時(shí),就會(huì)提示/自動(dòng)升級(jí)ActiveX控件了。