How to load your Office COM add-in on condition
A typical problem is: how to unload my add-in if a custom condition is met. The condition can be a specific user ("Don't load the add-in for this and that users") or user's permissions, Office version, etc. This blog is about how to solve this problem.
The host application e.g. Outlook or Excel loads your add-in if it is properly registered and if LoadBehavior is set to 3 in the registry. The exact registry branch depends on your add-in type:
- for a per-user add-in it is HKEY_CURRENT_USER\Software\Microsoft\Office\{host application}\Addins\{your add-in ProgId}
- for a per machine it is HKEY_LOCAL_MACHINE\Software\Microsoft\Office\{host application}\Addins\{your add-in ProgId}
This said, a way to prevent your add-in from loading is to set LoadBehavior = 0 in {HKLM and HKCU}\Software\Microsoft\Office\{host application}\Addins\{your add-in ProgId}. Naturally, modifying anything in HKLM requires administrative permissions and this means that a standard user cannot turn off a per-machine add-in. There's an exception however: Office 2010 allows a standard user to turn a per-machine add-in off by unchecking the add-in in the COM Add-ins dialog. This creates HKCU\Software\Microsoft\Office\{host application}\Addins\{your add-in ProgId} and puts LoadBehavior=2 there!
The above is applicable only before the host application starts loading the add-in. But after the host application starts loading the add-in, you cannot do anything to stop the process.
The correct way in this situation is to disable the UI as well as event handling in your add-in. That is, you move the focus from "add-in loading / unloading" to "add-in functioning or not functioning". This is demonstrated by the add-in project accompanying the article. The idea is to remove all components from the add-in module before Add-in Express processes the components to create the corresponding UI elements such as toolbars and Ribbons.
C#:
private void RemoveComponents() { for (int i = this.components.Components.Count - 1; i >= 0; i--) this.components.Remove(this.components.Components[i]); }
VB.NET:
Private Sub RemoveComponents() For i As Integer = Me.components.Components.Count - 1 To 0 Step -1 Me.components.Remove(Me.components.Components(i)) Next i End Sub
The method above must be run in the very first event the add-in fires. There are two candidates: AddinInitialize and OnRibbonBeforeCreate. The former is always the first event your add-in receives when loaded by a non-Ribbonned Office application e.g. Excel 2000-2003; sometimes it occurs first in a Ribbonned application e.g. Excel 2007-2010. OnRibbonBeforeCreate usually occurs first in Ribbonned applications. Pay attention to these “always” and “usually”.
Theoretically, there are two more ways: a) to fire an exception in AddinInitialize and b) to find an Office.COMAddin object corresponding to your add-in in the Application.COMAddins collection of the host application and set COMAddin.Connect = false.
However, both smell. Throwing an exception will set LoadBehavior=2 and your add-in will never have a chance to decide whether to load or not. Setting COMAddin.Connect=false is somewhat better but doesn’t it resemble pulling yourself up by your own hair to escape from a swamp? I don't recommend going this route: it may work for you now and fire an exception for the customer.
In case the condition is "the user loading the add-in belongs (or does not belong) to some user group", just everything above isn't required if you install the add-in via Group Policy: an administrator may uninstall the add-in for such users. We describe installing using Group Policy in HowTo: Install a COM add-in automatically using Windows Server Group Policy. If you use Add-in Express, step-by-step instructions on preparing your add-in for installation via Group Policy are here.
Good luck!
Available downloads:
These sample COM Add-ins were developed using Add-in Express for Office and .net:
2 Comments
I have build a Outlook Addin (2007 and newer) witch contains a adxOIFormsManager and one ADXOIForm with FormCollectionItem Settings ExplorerLayout: BottomSubpane, ExporerItemTypes: olMailItem, InspectorItemTypes olMail. When i run the Addin the Form will displayed as expected.
Now i try to stop the Addin Load Procedure by implementing the AddinModule_AddinInitialize Event as described in the Article:
private void AddinModule_AddinInitialize(object sender, EventArgs e)
{
RemoveComponents();
}
private void RemoveComponents()
{
for (int i = this.components.Components.Count – 1; i >= 0; i–)
this.components.Remove(this.components.Components[i]);
}
When i now Run the Addin, the Form ist still created even if the RemoveComponent() Method is called. When i debug step by step througth the RemoveComponents() Method called by AddinModule_AddinInitialize, i can see the removal of the two ComponentCollection Entries
[0] [AddinExpress.OL.ADXOlFormsManager]
[1] [AddinExpress.OL.ADXOlFormsCollectionItem]
and at the End of the RemoveComponent() Method the ComponentCollection ist empty.
Why does the above Method not work on ADXOlFormsManager / ADXOlFormsCollectionItem Elements and how can i remove a Outlook Forms Addin ?
I use Addin Express Version 6.6.3059
Thank you for your Answer
That was my fault after all. Sorry for this.
You need to clear the Items collection of the manager in the ADXOlFormsManager.OnInitialize event:
adxOlFormsManager1.Items.Clear();
In other host applications, you deal with this in the same way, see ADXExcelTaskPanesManager.ADXInitialize, ADXWordTaskPanesManager.ADXInitialize and ADXPowerPointTaskPanesManager.ADXInitialize events.
Thank you for pointing me to this!