not quite minimalistic enough  

A Bitmap, wrapped in a knotted Ribbon.

Writing Office add-ins has always been a bit of a dark art because there is not really all that much documentation, and what there is, tends to, let’s say, have been overtaken by events.

This is particularly true where VSTO, the Visual Studio Tools for Office, otherwise known as the .NET wrappers around the COM add-in API, is concerned. Even a seemingly simple task like finding out correct signatures for callback methods can be surprisingly difficult because the authoritative page still only mentions Office 2007, and you can never know what may have changed in the last 13 years. (Wow. Has it been that long?)

OK, enough of the empty complaining. Let’s get to the useful information. Everything below is based on current Office 365 with the latest VSTO version as of today, 10.0.60724.

The loadImage callback

The correct C# signature for the callback method named in <customUI loadImage="LoadImageCallback"> is:

public Bitmap LoadImageCallback(string imageId)

There are various discussions around the Internet on whether this method should return Bitmap or stdole.IPictureDisp, or whether Bitmap works everywhere except Outlook.

Bitmap works everywhere including Outlook.

Namespaces and idQ

When using the idQ attribute to identify controls, you may notice that your callbacks aren’t. Called, that is. This is explained in a paragraph about one-third down the page linked above:

If you use a COM add-in to customize the Fluent UI, the namespace name must be the ProgID of the COM add-in, but the behavior is otherwise the same. When you use a shared add-in, the ProgID is AddInName.Connect. When you use Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System (Visual Studio 2005 Tools for Office Second Edition) to create the add-in, the ProgID is the name of the add-in.

(Emphasis mine.)

VSTO is actually older than the W3C recommendation on “Namespaces in XML 1.0”, Second Edition, so I have to admit that the idea did not contradict the spec at the time. (The original recommendation from 1999 mentioned that the intent was to use URIs, but did not yet require it.)

However, I fail to see the reason why the namespace ID must be the add-in’s name, unless it is the result of a very ugly shortcut in the implementation of the “Fluent” UI, i.e. the Ribbon. It would be entirely simple for the host application to associate any string with the add-in whose GetCustomUI() returned the particular bit of XML.

By the way, the “name of the add-in” in the VSTO case above, that the namespace ID has to match, is the name of the subkey of SOFTWARE\Microsoft\Office\...\Addins. In addition to being true empirically, it also matches the non-VSTO case because the only place where the ProgID is involved in the process of loading an add-in is that Registry key.

Written on September 16, 2020