Arnout's Eclectica

But I digress…

Registration-free COM

31 March 2007 0:40 — COM,Development,Windows

A while ago, I had the following problem:

  • The build system needed to run a unit test of some code that depended on some COM object.
  • That COM object was not installed on the build system (it wasn't a part of the system we were developing).
  • Installing that COM object would mean having to install a large system with all kinds of dependencies — not exactly something I wanted to do on the build machine...

Fortunately, the interaction with the particular COM object was very basic. I made a fake implementation of it, just returning hard-coded responses for the few calls I needed. With the fake COM object in place, the unit tests passed.

I added some logic to the build file that checks whether a particular ProgID existed in the registry. If not, the build script registers the fake object, runs the specific tests, and then unregisters it again.
If the ProgID is found in the registry, however, just the tests are executed. This allows the build to be also run on a developer's machine containing the back-end system (and not mess up its COM registration). Works great.

Fast-forward to yesterday.

Triggered by a discussion with a co-worker about the fact that the unit tests aren't nicely isolated from the back-end system this way, I suddenly remembered reading about registration-free COM on Junfeng Zhang's blog.

Registration-free COM

As the name implies, registration-free COM makes it possible to use COM objects without registering them. An application gets all activation information (typelib, ProgID-to-CLSID mapping, threading model and the like) from a manifest file, instead of reading it from the registry. This allows multiple applications to use different versions of a COM object, with the same ProgID and/or CLSID.

That's a much nicer solution for my original problem — I no longer have to dynamically register and unregister my fake implementation, and I can use the fake implementation on systems containing the real one as well.

A sample manifest file

The manifest file I'm using looks like this:

<?xml version='1.0' encoding='utf-8'?>
<assembly manifestVersion='1.0' xmlns='urn:schemas-microsoft-com:asm.v1'>
  <assemblyIdentity type='win32' name='RegFreeCOM-sample.exe' version='1.0.0.0' />
  <file name='FakeTCMXML.dll'>
    <comClass clsid='{69c2082a-61b1-4a83-a947-88420fac54fa}'
              threadingModel='Apartment'
              progid='TCMXML.XMLResponder' />
  </file>
</assembly>

I've saved this as RegistrationFreeCOM.exe.manifest in the same directory as my test application RegistrationFreeCOM.exe, and also copied my fake implementation FakeTCMXML.dll into that directory. The test application will activate TCMXML.XMLResponder from FakeTCMXML.dll, regardless of whether that ProgID already occurs in the registry, and without affecting that registration.

Creating a manifest file

For many scenarios, the sample manifest file is sufficient: just update the 'name', 'clsid' and 'progid' attributes. You can find the value for 'clsid' in the IDL for your component, or by using OleView.
You can also have Visual Studio 2005 create a manifest file for you: create a throw-away project, reference your COM dll, view the properties of that reference, and toggle the 'Isolated' flag to 'True'. When you build the project, the manifest file will be generated.

2 Comments »

  1. Hi Arnout,

    I am wondering if this is possible without creating an application manifest?

    My scenario is different in that I am using a third party test runner exe, winunit.exe.

    Any ideas?

    Thank you.

    Comment by Rami AbuGhazaleh — 16 June 2011 @ 22:17

  2. Rami,

    Sorry, took me a while to find the time to look at this.

    I’ve never used it before, but there’s an Activation Context API. Using that API, you can explicitly control which manifest file (or resource) to use, instead of having Windows default to appname.exe.manifest.

    I built a quick test project, and that worked nicely (note that the sample code on MSDN seems to lack a call to ReleaseActCtx() — not sure how important that is, but still). I assume this would work as well from a WinUnit test DLL, but I didn’t try that.

    Comment by Arnout — 19 June 2011 @ 20:55

RSS feed for comments on this post. TrackBack URI

Leave a comment

Copyright © 2006-2009 Arnout Grootveld — Powered by WordPress — Hosted at pair Networks