My Add-in Project Doesn’t Work Anymore–What Happened?

A common issue that occurs in add-in development goes like this.  “I just pressed F5 on my add-in project and nothing happens!  My add-in doesn’t appear to load.  What’s the deal”?

Office has a system to protect itself from Add-ins gone wild.  Once you understand the system, you will better understand how to protect against your add-in not loading. 

Office automatically disables an add-in if it detects that it crashed the host application while starting up.  When the Office application loads and starts an add-in, it puts a sentinel in the registry associated with the add-in that it is loading.  It then calls the add-in’s OnConnection and OnStartupComplete methods.  If the add-in successfully returns from these two methods, Office removes the sentinel in the registry and everything works fine.  If the add-in crashes in OnConnection or OnStartupComplete or you stop debugging and kill the Outlook process before OnConnection or OnStartupComplete return then the sentinel is still sitting in the registry.  When you relaunch the Office application, Office detects that a sentinel got left in the registry on the last run and it disables your add-in.

It is very easy to have this happen during development—you might be stepping through code invoked by your OnConnection or OnStartupComplete entry point and you get to a line of code and say to yourself—this line of code is completely wrong.  You then stop debugging and change the code and press F5 to rerun the add-in.  But on the second run the add-in doesn’t work.  Office detects the sentinel in the registry left over from the last run when you killed the process in the middle of OnConnection or OnStartupComplete and it disables your add-in.

The situation is even worse for un-shimmed managed add-ins.  (Shim your managed add-in please).  The sentinel put in the registry for a managed add-in is the name of the dll that bootstraps the add-in.  In the case of a non-shimmed add-in, the bootstrap dll is always mscoree.dll—a component of the CLR.  Mscoree.dll acts as a class factory to create COM objects implemented in managed code for a host like Office that expects a COM object that implements IDTExtensibility2.  It bootstraps the CLR into the Office application process, loads the managed add-in registered in the registry, and gives the Office application the managed add-in class that implements IDTExtensibility2 and through interop makes that class looks like a COM object to Office.  So let’s say you have two add-in projects—Addin1 and Addin2—both of which are unshimmed.  You are debugging Addin1’s OnConnection handler and you hit stop debugging in the middle of it.  This leaves the sentinel in the registry saying not that Addin1.dll crashed Office but that mscoree.dll crashed Office.  Now you open the Addin2 project and run it and because Addin2 is also registered with mscoree.dll as its class factory both Addin1 and Addin2 (and any other unshimmed managed addins) will be disabled.

To undisable an add-in that has been disabled, go to the Help->About box of the Office application and click on the Disabled Items… button.  This will pop up a dialog that will let you reenable mscoree.dll for an unshimmed add-in or for a shimmed add-in whatever your shim dll name is. 

But wait—there’s more.  There is a second way your add-in can get disabled.  I know this occurs in Outlook—I haven’t verified it occurs in all the other Office applications.  If your add-in throws an exception in OnConnection or OnStartupComplete code and doesn’t catch it, that exception propagates out to Outlook and Outlook disables the add-in by setting the LoadBehavior key to 2.  (HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\Outlook\Addins\<<Add-in Name>>\LoadBehavior).  There is an easy way to deal with this issue.  Always put your code that handles OnConnection and OnStartupComplete inside a try..catch block.  Don’t leak any exceptions in OnConnection or OnStartupComplete back to Office. 

Comments (2)

  1. We have another way how our .Net add-in gets disabled, I was wondering if anyone knows a way around it. Steps to reproduce are as follows:

    1. use a PC that has Outlook 2003 and any current version of ActiveSync for PocketPC installed. Configure ActiveSync so that it synchronises Outlook items, e.g., your calendar

    2. Kill all OUTLOOK.EXE processes to start with a clean slate, but leave ActiveSync running. This mimics what happens when your PC boots and ActiveSync gets control.

    3. Now connect your Pocket PC (disconnect and reconnect if it already was connected). ActiveSync will synchronise the PocketPC and start an OUTLOOK.EXE process to get the outlook items to be synchronised.

    4a. Now open the Outlook main window and try your dotnet add-in. Ours doesn’t work 🙁

    4b. First kill the OUTLOOK.EXE process started by ActiveSync and THEN open the Outlook main window. The add-in works fine.

    This bug was documented by Microsoft for Outlook 2002 as, and according to the article fixed in Office XP SP3. We tried the registry setting described in the Office10.0 part of the registry and also same setting in Office11.0, but it definitely does not make any difference. We’re stuck 🙁

    Best regards,

    Berend Engelbrecht

  2. Perhaps a follow up is nice … we found out why the add-in doesn’t work in this setup: it tries to retrieve the ActiveExplorer window to add its commandbar and -button to Outlook, and there is no ActiveExplorer at that point in time when ActiveSync starts Outlook (makes sense).

    What we now do is to start a thread that waits for the ActiveExplorer to be created and then adds the commandbar and button. All is well, except for 1 thing: adding the button picture gives a "catastrophic failure" when done from the thread. The exact same code called directly at startup works fine. We tried creating a custom event handler and raising the event from the thread instead of calling the code directly, that did not make a difference: still everything works except adding the picture and mask to the button.

Skip to main content