Even Better COM Shims
We finalized the COM Shim Wizards some time ago, and they're up on msdn for download here:
http://www.microsoft.com/downloads/details.aspx?FamilyID=4c586367-c733-4c68-9971-373c180ec114&DisplayLang=en
...with the covering article here:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dno2k3ta/html/ODC_Office_COM_Shim_Wizards.asp
For a long time, people built managed extensions for Office - especially managed COM add-ins - without shims. The msdn article goes into detail about the whys and wherefores of shimming such extensions. The wizards make the process of building shims very straightforward.
That said, the shim wizards are not as polished and elegant as I'd like them to be. Over the last few months, we've been energetically discussing some design options as well as some deployment issues.
Things I'd like to fix in the next version of the shim (and thanks to Andrew Clinnick and Misha Shneerson for the good ideas - all the bad ideas are mine):
1. Make the shim install and work for Whidbey (this is actually done, but I haven't released this version because I want to squeeze in a couple of the other improvements before releasing an update).
2. The current shim wizards generate all the C++ code you need, and don't require you to touch that code, just build it. However, you do have to build it, and if you accidentally corrupt the code or if you change your mind about some crucial details, you then either have to re-run the wizard to generate fresh shim code (admittedly a no-brainer), or edit the code manually. Also, much of the internal functionality of the shim does not change from one extension to another.
So, what would be good is a 2-part shim. All the invariant internal stuff such as loading the CLR, creating a separate AppDomain, loading the managed extension, etc, can be done in a built component that can be deployed once and never needs to be re-generated. Then, all we need is a very thin outer component that simply instantiates the inner one at runtime and provides it with the necessary details of the specific managed extension to be loaded. There needn't be any particular perf penalty either, because as soon as the outer shim has loaded the inner shim, the inner shim would load the managed assembly and hand back a suitable interface pointer to the outer shim.
3. In its current form, the shim creates a separate AppDomain for the extension (for all the good reasons around isolation and security), but it doesn't unload that AppDomain until the host itself shuts down. This is mostly acceptable for Smart Tags and RTD components, but not always suitable for add-ins. For instance, (for HKCU-registered add-ins) the user can use the COM Add-ins dialog in Office to disconnect/reconnect an add-in without shutting down the host.
I've been working on a version of the shim that does unload the AD for an add-in specifically during IDTExtensibility2::OnDisconnection. Watch this space.
3. Excel Automation Add-ins. In the investment banking world, where I've been living for the last couple of years, the requirement for managed UDFs is extreme. It only takes a couple of minor tweaks to turn a regular COM add-in into an Automation add-in. So, it would be nice to build this into the wizard.
I've been working an yet another version of the shim that does this. The tricky part is that automation add-ins work through automation (surprise), and in fact through a registered type library. It's not feasible to bypass this mechanism, so it does mean generating wrapper code in the shim to the developer's arbitrary automation interface. My version generates C++ wrapper code from the typelib, but its a bit of a hack right now.
There are a few other trivial things I'd quite like to do, although none is particularly high priority, such as:
- templatizing the VERSIONINFO in the .rc templates.
- optionally asking the user to point us to their setup project (if they have one) for their extension from which we can harvest the registry information instead of asking them to enter it all again (this is mostly a nuisance for add-ins)
- maybe copy the target managed extension assembly to the target folder for the shim to ease development
- maybe update their setup project to include the primary output of the shim project, and adjust the two registration entries so that the shim gets registered while the extension doesn't.
What else? Oh yes, the book finally made it to the printers, and should be shipping 08-Nov: Microsoft .NET Development for Microsoft Office (Office/Progmng/Net)
http://www.amazon.com/exec/obidos/tg/detail/-/0735621322/qid=1095450834/sr=8-2/ref=sr_8_xs_ap_i2_xgl14/103-6053701-7610227?v=glance&s=books&n=507846
Thought for the day: You can only attach managed functionality to keystrokes via VBA. That is, you can add a KeyBinding in Word, or use OnKey in Excel to associate a keystroke combination with a VBA macro. You can then write your VBA macro to be a thin wrapper to some managed function. What you can't do is directly connect a keystroke to a managed function without using VBA in the middle. Does anyone care about this? Is this acceptable? Answers on a postcard...