Office的所有COM Add In,包括用Shared Add In模板和VSTO Add In模板創建的,都會在注冊表里面存儲一些信息。
對於當前用戶安裝的Add In,以Excel為例,對應的注冊表鍵值存儲於:My Computer/HKCU/Software/Microsoft/Office/Addins/AddInName;
機器級別的Add In存儲於:My Computer/HKLM/Software/Microsoft/Office/Addins/AddInName。
普通的Shared Add In, 鍵下面有3個值,Description,FriendlyName,LoadBehavior。
VSTO Add In多出兩個鍵值:CommandLineSafe和Manifest。Manifest是用來指向自定義代碼所處的dll位置的,CommandLineSafe用來指示Add In是不是命令行安全的,會不會顯示在COM Add In Dialog里面。Description和FriendlyName就是Add In的描述和顯示的名字,沒啥好說的。
而LoadBehavior是這篇文章的主角。LoadBehavior指示了該Add In的裝載行為,它可以由以下幾個值組合而成: (前兩個中的一個+后三個中的一個)
0 = Disconnect |
不裝載 |
1 = Connected |
裝載 |
2 = Bootload |
啟動程序時裝載 |
8 = DemandLoad |
需要時裝載 |
16 = ConnectFirstTime |
第一次啟動時裝載 |
也就是說,當LoadBehavior為0,2,8,16的時候,Add In不裝載;當其為1+2=3的時候,裝載並且每次Office程序啟動時都裝載;當其為9的時候,裝載,但只當用戶需要時裝載;17的時候,裝載,只有第一次啟動的時候裝載。如果我們不去改動,一般而言,正常工作的Add In其LoadBehavior是3,但如果當Add In啟動的時候發生異常,這個Add In會被軟禁用(Soft Disabled),LoadBehavior的值會被改為0+2=2,Add In將不被裝載。注意,雖然這里的值是2,表示啟動時裝載,但事實上,其是由0+2所得,大的前提決定了不裝載。
那我說的LoadBehavior的妙用在何處呢?這源於最近碰到的一個問題,有人問我,能不能用代碼來獲取Office中被硬禁用(Hard Disable)的COM Add In,或者至少知道,有沒有被硬禁用的Add In?這個問題有點棘手,因為Office對象模型中,根本找不到任何信息。Google甚至都找不到,有人有類似的要求。
在給出解決方案前,有必要講述一下,上面提到的硬禁用和軟禁用的區別。首先,硬禁用和軟禁用的表象就不一樣,被軟禁用的Add In會出現在COM Add-Ins對話框中,只不過前面的Checkbox不會被勾上。被硬禁用的Add In雖然也會出現在COM Add-Ins對話框中,但它們會被單獨再列到另外一個叫Disabled Items的對話框里面。下面是COM Add-Ins對話框和Disabled Items對話框的截圖。由下面的圖可以看出來ExcelAddIn和ExcelAddIn1是被用戶手動禁用,或者被軟禁用的;ExcelAddIn2則是被硬禁用的。
COM Add-Ins對話框截圖
Disabled Items對話框截圖
那是什么導致Add In被軟禁用和硬禁用的呢?為了模擬出問題,並解決,我也必須讓自己的機器上出現一個被軟禁用,一個被硬禁用的Add In。
軟禁用:當Add In在構造函數或者Startup event handle函數里面拋出一個沒有處理的異常的時候,系統將該Add In軟禁用,將其LoadBehavior值改為2。要重現一個軟禁用很簡單,在Startup event handle里面拋出一個異常就可以了,代碼如下:
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
throw new Exception("Make the Add in disabled");
}
硬禁用:發生在,Add In裝載時由於嚴重的錯誤導致應用程序關閉,或者在構造函數或Startup event handle函數執行時,強行關掉Visual Studio Debugger時。這將導致再一次啟動應用程序的時候,Office向用戶詢問是否硬禁用當前Add In。方法同樣很簡單,用一個MessageBox停住Startup event handle函數的執行過程,然后強行關掉Visual Studio,下次程序(本例Excel)啟動時,選擇禁用Add In。
private void ThisAddIn_Startup(object sender, System.EventArgs e)
{
MessageBox.Show("Stop here");
}
接下來,看看上面問題的解決方案。在Office對象模型中,Application對象有個COMAddIns屬性,它是一個集合,包括了當前應用程序中所有注冊過的COM Add In,無論這個Add In是否激活。我們可以在這個集合中循環,得到每個COMAddIn的句柄,而COMAddIn又暴露了一些有用的屬性,比如Connect屬性。當Connect返回true時,說明這個Add In是激活的,如果返回false,說明這個Add In未激活,有可能是被用戶手動禁用了,還有可能是被軟禁用或硬禁用了。但是COMAddIn的屬性只告訴我們這么多,通過Office對象模型,我們無法分辨,應用程序中是否存在被硬禁用的Add In,如果有,哪些是被硬禁用的Add In。通過查看硬禁用的Add In在注冊表中LoadBehavior的值,驚奇地發現,硬禁用的Add In,其LoadBehavior值竟然為3!這樣我們就可以結合COMAddIns集合和注冊表里LoadBehavior的信息來判斷哪些COM Add In是被硬禁用的,哪些是由於軟禁用或者其它原因未被裝載的。實現的代碼如下:
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對話框?(沒有中文的Office,所以菜單和按鈕都按英文版中的寫法,對照着應該很好找到)
- · COM Add-ins對話框:
- o Office 2007:Office Button->Excel Options->Add-Ins Tab->Choose Item COM Add-ins in theManage DropDownList->Click Button Go
- o Office 2003:Right Click the Menu->Click Customize… Button->In Commands Tab->ToolsCategorie->Drag COM Add-Ins Command to one of the tool bar->Click the new added COM Add-ins Button
- · Disabled Items對話框:
- o Office 2007:Office Button->Excel Options->Add-Ins Tab->Choose Item Disabled Items in theManage DropDownList->Click Button Go
- o Office 2003:Menu Help->About Microsoft Office Excel->Disabled Items