In our spare time, Misha and I have been working on and off on the COM Shim and associated COM Shim Wizards for the last few years, and we’ve just published a new version here: Isolating Microsoft Office Extensions with the COM Shim Wizard Version 2.3, with the accompanying download here.
The new version includes all the old projects for smart tags and RTD components – these have not changed since the previous version. The significant changes in the new version are all in the add-in shim and the add-in shim project wizard. Apart from minor bug fixes and code cleanup, the changes all relate to the new extensibility interfaces introduced with Office 2007. All the new interfaces are now supported in the shim (including IDocumentInspector, which is kind of redundant, but included for completeness). See my previous post on the new interfaces: Office 2007 New Extensibility Interfaces.
In another post, Why is it so hard to shim IRibbonExtensibility?, I discussed the reasoning behind the change in the shim design. Basically, it comes down to the need to support the potentially undefined methods on an automation interface (like IRibbonExtensibility). The IRibbonExtensibility interface only defines one method (GetCustomUI), but Office will expect to be able to call back on your IRibbonExtensibility object for any number of additional methods that are not defined in the interface. This is standard behavior for automation interfaces. For example, in your ribbon XML, you might specify that the callback method for a button is say MyButtonCallbackMethod, a method that is obviously not defined in the IRibbonExtensibility interface. Office uses the IDispatch interface implemented by all automation objects to call back on these “undefined” methods.
The same model is used for Excel automation add-ins. These can implement IDTExtensibility2, but they don’t have to. Indeed, they don’t have to implement any defined interface beyond IDispatch (the automation interface). All the UDFs will be automation methods.
The old add-in shim (and the shim for smart tags and RTD components) uses containment to proxy the defined method calls on the specific interfaces that the shim is shimming (IDTExtensibility2, ISmartTagRecognizer, ISmartTagAction, IRtdServer, etc). The new add-in shim still uses containment for the known interface it proxies (IDTExtensibility2), but it uses aggregation for the automation interfaces used in Ribbon customization and Excel automation add-ins (and potentially any other new automation interfaces that Office might introduce in later releases).
To achieve this aggregation, there’s a bit of work to call Marshal.CreateAggregatedObject – this is a static method in a sealed abstract base class in the .NET base class library. In order to call this from the (unmanaged) shim, we have to instantiate a tiny managed component to call it on our behalf. Hence the shim is now slightly more complex than it was – in that, it now has 2 pieces, one unmanaged (as before) and one managed. If you read my previous discussion of the reasoning behind this design, you’ll realize that we could have built the new shim in a much simpler way by overriding QueryInterface and blindly aggregating all the interfaces that we don’t proxy by containment. Right now, this would probably work, because right now Office doesn’t transition from any of these interfaces to any other interfaces. But, this model would break COM identity rules, and your shim would be broken if Office ever decided to optimize their interface querying differently from the way they do now. So, the slight added complexity of 2 pieces in the new shim is the price we pay for a robust model that is resilient to future changes, and doesn’t break any rules.
Our day job (or night job, in Misha’s case) is building VSTO, so it might seem strange that we spend our spare time building tools and components that support an alternative add-in model to VSTO. The simple fact is that we recognize that VSTO add-ins do not cover the totality of customer requirements (for example, no support for versions of Office earlier than 2003, and for “minor” Office apps such as Publisher). The main reason that VSTO doesn’t support all permutations is that the test matrix would be fantastically large. Everything is a trade-off, and we believe the trade-off between shipping good tools that cover some large percentage of customer requirements in a reasonable time frame, versus shipping tools that cover 100% of requirements in an unreasonably long time frame, is an optimal one. So, use VSTO where you can – and for those scenarios where you can’t, do shim your add-ins, and you can use the COM Shim Wizard tool to help you build suitable shims.