Share via


Writing a shim to solve problems with managed Office COM Add-ins

If you’ve been following my and Omar’s blogs lately, you’ll know that we’ve been learning a lot about writing managed Outlook COM Add-ins and running into lots of complications in the process. Here I describe how a shim can help solve some of these problems. The issues here apply to all Office add-ins, not just Outlook (although the trust model for Outlook is a bit different).

Running in your own AppDomain

It’s amazing how you can write .NET code to define a COM interface, and the marshalling between the programming models is taken of for you magically. This is done through the Runtime Callable Wrapper (RCW). The complications come from the fact that the RCW is shared between all add-ins. There are also complications based on which version of the primary interop assembly (PIA) you install and which other add-ins install (and where). And, finally, if memory isn’t cleaned up properly, Outlook might fail to quit, but you can’t call ReleaseCOMObject from an add-in because that RCW may be in use by other add-ins. For more details, see Omar’s tales of woe here, and warnings around ReleaseCOMObject here, here, and here.

A shim solves this problem having an unmanaged COM add-in that simply loads your managed add-in into a new AppDomain and then proxies everything to your add-in. It doesn’t even require changes to your managed code.

Signing your add-in

The trust model for Outlook add-ins is a bit complicated. If your add-in is not signed, depending on your Outlook settings, the add-in may silently load, prompt on startup, or silently not load. If you digitally sign your add-in with a self-signed certificate, the add-in will silently load with most configurations. See the table here for the nitty gritty details. The problem is that when you write a managed plugin, mscoree.dll is the dll that’s registered to be loaded, and it takes care of loading your managed code, and mscoree.dll is not signed. That means, even if you sign your managed code, Outlook will see your add-in as unsigned.

The shim comes to the rescue again. You can sign your managed code, and then sign your shim. The shim loads your managed code as a strongly named assembly, which verifies that the shim is loading the right code. This step is very important. If you just signed the shim and not the managed code, then someone could replace your managed code with something malicious, and it would still appear signed to Outlook.

Implementing a shim

I was originally hoping to provide step by step instructions to write a shim here. However, there are just way too many steps, and they are described pretty well on MSDN. They even include an Excel spreadsheet to mark off the steps as you go! The introductory article is here, and then the step by step instructions are here. There are a couple of typos, but it’s otherwise explained pretty well. There are a couple of points worth noting if you adding this to an existing managed plugin that you created from the VS template:

  1. You’ll want to remove the primary output of the managed add-in from the setup project and follow the steps on the page. You’ll add the managed assembly to the setup project, and the primary output of the shim project.
  2. This is buried in the notes at the end, but you’ll have to turn off the “Register for COM Interop” setting for the managed add-in project. To do so, right-click the project, choose properties, and then go to Configuration Properties->Build and set Register for COM Interop to false.

Also, you can skip the signing part of the shim if you just want to solve the AppDomain related problems. To do so, just set szAddInAssemblyName to the assembly name without the PublicKeyToken part. As mentioned above, sign neither of the components or both of them. Don’t mix.

I’d be happy to help anyone that runs into trouble creating a shim. Just post a comment!