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.