|
Office的所有COM Add In,包括用Shared Add In模板和VSTO Add In模板創(chuàng)建的,都會(huì)在注冊(cè)表里面存儲(chǔ)一些信息。 對(duì)于當(dāng)前用戶安裝的Add In,以Excel為例,對(duì)應(yīng)的注冊(cè)表鍵值存儲(chǔ)于:My Computer/HKCU/Software/Microsoft/Office/Addins/AddInName; 機(jī)器級(jí)別的Add In存儲(chǔ)于:My Computer/HKLM/Software/Microsoft/Office/Addins/AddInName。 普通的Shared Add In, 鍵下面有3個(gè)值,Description,FriendlyName,LoadBehavior。 VSTO Add In多出兩個(gè)鍵值:CommandLineSafe和Manifest。Manifest是用來(lái)指向自定義代碼所處的dll位置的,CommandLineSafe用來(lái)指示Add In是不是命令行安全的,會(huì)不會(huì)顯示在COM Add In Dialog里面。Description和FriendlyName就是Add In的描述和顯示的名字,沒(méi)啥好說(shuō)的。 而LoadBehavior是這篇文章的主角。LoadBehavior指示了該Add In的裝載行為,它可以由以下幾個(gè)值組合而成: (前兩個(gè)中的一個(gè)+后三個(gè)中的一個(gè))
也就是說(shuō),當(dāng)LoadBehavior為0,2,8,16的時(shí)候,Add In不裝載;當(dāng)其為1+2=3的時(shí)候,裝載并且每次Office程序啟動(dòng)時(shí)都裝載;當(dāng)其為9的時(shí)候,裝載,但只當(dāng)用戶需要時(shí)裝載;17的時(shí)候,裝載,只有第一次啟動(dòng)的時(shí)候裝載。如果我們不去改動(dòng),一般而言,正常工作的Add In其LoadBehavior是3,但如果當(dāng)Add In啟動(dòng)的時(shí)候發(fā)生異常,這個(gè)Add In會(huì)被軟禁用(Soft Disabled),LoadBehavior的值會(huì)被改為0+2=2,Add In將不被裝載。注意,雖然這里的值是2,表示啟動(dòng)時(shí)裝載,但事實(shí)上,其是由0+2所得,大的前提決定了不裝載。
那我說(shuō)的LoadBehavior的妙用在何處呢?這源于最近碰到的一個(gè)問(wèn)題,有人問(wèn)我,能不能用代碼來(lái)獲取Office中被硬禁用(Hard Disable)的COM Add In,或者至少知道,有沒(méi)有被硬禁用的Add In?這個(gè)問(wèn)題有點(diǎn)棘手,因?yàn)?span style="FONT-FAMILY: Calibri">Office對(duì)象模型中,根本找不到任何信息。Google甚至都找不到,有人有類似的要求。 在給出解決方案前,有必要講述一下,上面提到的硬禁用和軟禁用的區(qū)別。首先,硬禁用和軟禁用的表象就不一樣,被軟禁用的Add In會(huì)出現(xiàn)在COM Add-Ins對(duì)話框中,只不過(guò)前面的Checkbox不會(huì)被勾上。被硬禁用的Add In雖然也會(huì)出現(xiàn)在COM Add-Ins對(duì)話框中,但它們會(huì)被單獨(dú)再列到另外一個(gè)叫Disabled Items的對(duì)話框里面。下面是COM Add-Ins對(duì)話框和Disabled Items對(duì)話框的截圖。由下面的圖可以看出來(lái)ExcelAddIn和ExcelAddIn1是被用戶手動(dòng)禁用,或者被軟禁用的;ExcelAddIn2則是被硬禁用的。
COM Add-Ins對(duì)話框截圖
Disabled Items對(duì)話框截圖 那是什么導(dǎo)致Add In被軟禁用和硬禁用的呢?為了模擬出問(wèn)題,并解決,我也必須讓自己的機(jī)器上出現(xiàn)一個(gè)被軟禁用,一個(gè)被硬禁用的Add In。 軟禁用:當(dāng)Add In在構(gòu)造函數(shù)或者Startup event handle函數(shù)里面拋出一個(gè)沒(méi)有處理的異常的時(shí)候,系統(tǒng)將該Add In軟禁用,將其LoadBehavior值改為2。要重現(xiàn)一個(gè)軟禁用很簡(jiǎn)單,在Startup event handle里面拋出一個(gè)異常就可以了,代碼如下: private void ThisAddIn_Startup(object sender, System.EventArgs e) { throw new Exception("Make the Add in disabled"); } 硬禁用:發(fā)生在,Add In裝載時(shí)由于嚴(yán)重的錯(cuò)誤導(dǎo)致應(yīng)用程序關(guān)閉,或者在構(gòu)造函數(shù)或Startup event handle函數(shù)執(zhí)行時(shí),強(qiáng)行關(guān)掉Visual Studio Debugger時(shí)。這將導(dǎo)致再一次啟動(dòng)應(yīng)用程序的時(shí)候,Office向用戶詢問(wèn)是否硬禁用當(dāng)前Add In。方法同樣很簡(jiǎn)單,用一個(gè)MessageBox停住Startup event handle函數(shù)的執(zhí)行過(guò)程,然后強(qiáng)行關(guān)掉Visual Studio,下次程序(本例Excel)啟動(dòng)時(shí),選擇禁用Add In。 private void ThisAddIn_Startup(object sender, System.EventArgs e) { MessageBox.Show("Stop here"); }
接下來(lái),看看上面問(wèn)題的解決方案。在Office對(duì)象模型中,Application對(duì)象有個(gè)COMAddIns屬性,它是一個(gè)集合,包括了當(dāng)前應(yīng)用程序中所有注冊(cè)過(guò)的COM Add In,無(wú)論這個(gè)Add In是否激活。我們可以在這個(gè)集合中循環(huán),得到每個(gè)COMAddIn的句柄,而COMAddIn又暴露了一些有用的屬性,比如Connect屬性。當(dāng)Connect返回true時(shí),說(shuō)明這個(gè)Add In是激活的,如果返回false,說(shuō)明這個(gè)Add In未激活,有可能是被用戶手動(dòng)禁用了,還有可能是被軟禁用或硬禁用了。但是COMAddIn的屬性只告訴我們這么多,通過(guò)Office對(duì)象模型,我們無(wú)法分辨,應(yīng)用程序中是否存在被硬禁用的Add In,如果有,哪些是被硬禁用的Add In。通過(guò)查看硬禁用的Add In在注冊(cè)表中LoadBehavior的值,驚奇地發(fā)現(xiàn),硬禁用的Add In,其LoadBehavior值竟然為3!這樣我們就可以結(jié)合COMAddIns集合和注冊(cè)表里LoadBehavior的信息來(lái)判斷哪些COM Add In是被硬禁用的,哪些是由于軟禁用或者其它原因未被裝載的。實(shí)現(xiàn)的代碼如下: private void ThisAddIn_Startup(object sender, System.EventArgs e) { RegistryKey key = null;
foreach(Office.COMAddIn cAddin in this.Application.COMAddIns) { if (!cAddin.Connect) { try { key = Registry.LocalMachine; key = key.OpenSubKey("Software").OpenSubKey("Microsoft") .OpenSubKey("Office").OpenSubKey("Excel").OpenSubKey("Addins") .OpenSubKey(cAddin.ProgId); if (Convert.ToInt32(key.GetValue("LoadBehavior")) == 3) { MessageBox.Show(cAddin.ProgId + " is disabled!"); } else { MessageBox.Show(cAddin.ProgId + " is not loaded!"); } } catch(Exception ex) { key = Registry.CurrentUser; key = key.OpenSubKey("Software").OpenSubKey("Microsoft") .OpenSubKey("Office").OpenSubKey("Excel").OpenSubKey("Addins") .OpenSubKey(cAddin.ProgId); if (Convert.ToInt32(key.GetValue("LoadBehavior")) == 3) { MessageBox.Show(cAddin.ProgId + " is disabled!"); } else { MessageBox.Show(cAddin.ProgId + " is not loaded!"); } } } } }
PS:如何顯示COM Add-ins和Disabled Items對(duì)話框?(沒(méi)有中文的Office,所以菜單和按鈕都按英文版中的寫法,對(duì)照著應(yīng)該很好找到)
|
|
|
來(lái)自: 實(shí)力決定地位 > 《VSTO》