Tuesday, June 8, 2010

How to fix Office plugin dependencies

I've been doing some development lately on an Outlook plugin and I've run in to a ridiculous number of issues messing with references, particularly when I have been using 3 different versions of Outlook and uninstalling/reinstalling them continuously. As a result, I've had to figure out a lot about how these interop assemblies and COM objects work. In this post, I will share what I've learned over the last week or so in hopes that it will help others who are using popular search engines to try to figure this out.

How to make a plugin

To develop a plugin isn't horribly difficult. The dependencies you need are as follows:

Office Interop- you need the interop assemblies for the plugin to function. These are also referred to as the Primary Interop Assemblies (PIA's) Often these are installed with Office but you can download them manually if you need to. These are referenced as a COM object. More on that in a minute.

Visual Studio tools for Office- you need these also. You can get one version of them here: http://www.microsoft.com/downloads/details.aspx?familyid=5e86cab3-6fd6-4955-b979-e1676db6b3cb&displaylang=en The dll's here will live in the GAC.

For both of these, you'll need to reference the appropriate component for the Office program that you're targeting. For example, I am working with Outlook, so I need the Outlook PIA's to be referenced. The installer you download should have PIA's for all the office products so you shouldn't have to worry so much about that.

Office.Tools.Common- these are the common tools for office that you need for any addin you build (at least as far as I can tell). Also installed with VSTO so you should have them.

The version you need of these depends on what version of Office you're building for, although in theory these are backwards compatible, so if you build a plugin for Office 2003, then it should (in theory) be able to install and run on later versions of Office. I've had some success with this so far; the only issues I've had is with building.


I can't find the reference- the dreaded yellow exclamation point!

I've noticed that I tend to get a lot of build errors relating to these dependencies and not being able to find them. In 90% of the cases, this involves having installed multiple versions of Office or the PIA's, so in general all you have to do is fix the references.

Another error you may see is something like "HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)" which means that Visual Studio can't figure out where the .dll is that you're trying to reference, most likely because that dll doesn't exist.

Unfortunately, fixing this involves messing with registries, which is never fun. I'm going to walk you through it as it's not that hard if you know what you're looking for.

FIRST: BACK UP YOUR REGISTRIES!!!! Don't "pull an Atwood," be sure you have a good backup.

Fixing the COM stuff:

If you bring up the properties for the "Outlook" (or other product) interop assemblies, you'll see that the identity is set to some sort of GUID that looks a lot like this: {00062FFF-0000-0000-C000-000000000046}\9.4\0\primary

The GUID identified the registry key under HKCR (HKEY_CLASSES_ROOT)\typelib. If this is messed up, it's usually because there are multiple versions of this thing installed, so open regedit and navigate to HKCR\TypeLib\{00062FFF-0000-0000-C000-000000000046} and look at the sub keys. You'll see 1.0 and 2.0 (most likely). Expand 2.0 and you should see 0, flags, and helpdir. Expand 0. You may see both win32 and win64. If you see both, delete the one that you don't need (probably win64) because it means that Visual Studio is confused about which tlb to load. Next, the default key under win32 (or win64) will point to a .tlb file somewhere. Make sure that the file it points to exists. If it doesn't, point it to the right file OR nuke the key and re-install the PIA's. You may see that multiple COM objects are being used. Their GUID's will be under the same TypeLib key in the registries so check those for multiple versions and nuke the keys that point to stuff that isn't installed.

Next, check the stdole COM object the same way. Its key is is HKEY_CLASSES_ROOT\TypeLib\{00020430-0000-0000-C000-000000000046} and make sure that the file it points to exists and that there's only one entry.

Fixing the VSTO stuff

Next on the list is the VSTO dll's, which actually live in the GAC. There are a few things that can happen, but first nagivate to HKEY_CLASSES_ROOT\TypeLib\{00062FFF-0000-0000-C000-000000000046} and check for versions. You'll see various versions under there such as 9.4 (Office 2010) or 9.2 (Office 2007) and so on. I've found that previous office versions tend to stick around, and depending on what versions you have listed and what you actually reference and what's actually installed, you may find that there is a key that Visual Studio is using that points to something that doesn't actually exist. To fix this, delete all keys that are associated with versions of Office that you don't have installed. I had both 9.2 and 9.4 installed and when I nuked 9.2 (leaving 9.4, which was actually installed) then it started working again. Also, the same win32 and win64 problems can occur here as well, so be sure to delete what you don't need. Finally, check the default key under win32 and ensure that the file it points to exists and is the correct version for what you're building against.

This last one is a bit more annoying, because even if you delete the reference in Visual Studio and re-add it, it still might point to the wrong location because the registries are pointing to an invalid file.

Once you've gone through all of these, you should be able to build and run your addin and everything will be happy and good.

One more thing of note: if your addin can't be loaded, Office will change another registry key to prevent the addin from being loaded the next time Office starts. That key is located here: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office\\\Addins\ and will contain a DWORD called "LoadBehavior" that controls how Office will load that plugin. If the value is 3, it will automatically load the plugin when that Office product starts. If it's 2, it will not be loaded. In order to force your plugin to be loaded, change this value appropriately. Office will re-set it as soon as it tries and fails to load the plugin so be aware of this and ensure that it's correct, or you'll spend extra time trying to figure out why your plugin isn't working when the cause is just an incorrect setting.


I hope that this has been useful to someone; it took me a few days to figure all of this out.