<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Arnout's Eclectica &#187; COM</title>
	<atom:link href="http://grootveld.com/archives/category/com/feed" rel="self" type="application/rss+xml" />
	<link>http://grootveld.com</link>
	<description>But I digress...</description>
	<lastBuildDate>Wed, 10 Feb 2010 20:00:26 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Registration-free COM</title>
		<link>http://grootveld.com/archives/16/registration-free-com</link>
		<comments>http://grootveld.com/archives/16/registration-free-com#comments</comments>
		<pubDate>Fri, 30 Mar 2007 22:40:25 +0000</pubDate>
		<dc:creator>amg</dc:creator>
				<category><![CDATA[COM]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://grootveld.com/archives/16</guid>
		<description><![CDATA[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 [...]]]></description>
			<content:encoded><![CDATA[<p>A while ago, I had the following problem:</p>
<ul>
<li>The build system needed to run a unit test of some code that depended on some COM object.
</li>
<li>That COM object was not installed on the build system (it wasn't a part of the system we were developing).
</li>
<li>Installing that COM object would mean having to install a large system with all kinds of dependencies &mdash; not exactly something I wanted to do on the build machine...</li>
</ul>
<p>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.</p>
<p>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.<br />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.</p>
<p>Fast-forward to yesterday.</p>
<p>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 <a href='http://blogs.msdn.com/junfeng/archive/2006/04/20/579748.aspx' title='Junfeng Zhang&apos;s blog post about registration-free COM'>Junfeng Zhang&apos;s blog</a>.</p>
<h3>Registration-free COM</h3>
<p>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 <a href='http://msdn2.microsoft.com/en-us/library/aa375632.aspx' title='Description of side-by-side manifest and configuration files at http://www.microsoft.com'>manifest file</a>, 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.</p>
<p>That's a much nicer solution for my original problem &mdash; 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.</p>
<h3>A sample manifest file</h3>
<p>The manifest file I'm using looks like this:</p>
<pre class='codesample'>
<span class='TPXMLkw1'>&lt;</span>?xml <span class='TPXMLkw2'>version</span>=<span class='TPXMLstr'>&apos;1.0&apos; </span><span class='TPXMLkw2'>encoding</span>=<span class='TPXMLstr'>&apos;utf-8&apos;</span>?<span class='TPXMLkw1'>&gt;</span>
<span class='TPXMLkw1'>&lt;</span>assembly <span class='TPXMLkw2'>manifestVersion</span>=<span class='TPXMLstr'>&apos;1.0&apos; </span><span class='TPXMLkw2'>xmlns</span>=<span class='TPXMLstr'>&apos;urn:schemas-microsoft-com:asm.v1&apos;</span><span class='TPXMLkw1'>&gt;</span>
  <span class='TPXMLkw1'>&lt;</span>assemblyIdentity <span class='TPXMLkw2'>type</span>=<span class='TPXMLstr'>&apos;win32&apos; </span><span class='TPXMLkw2'>name</span>=<span class='TPXMLstr'>&apos;RegFreeCOM-sample.exe&apos; </span><span class='TPXMLkw2'>version</span>=<span class='TPXMLstr'>&apos;1.0.0.0&apos; </span>/<span class='TPXMLkw1'>&gt;</span>
  <span class='TPXMLkw1'>&lt;</span>file <span class='TPXMLkw2'>name</span>=<span class='TPXMLstr'>&apos;FakeTCMXML.dll&apos;</span><span class='TPXMLkw1'>&gt;</span>
    <span class='TPXMLkw1'>&lt;</span>comClass <span class='TPXMLkw2'>clsid</span>=<span class='TPXMLstr'>&apos;{69c2082a-61b1-4a83-a947-88420fac54fa}&apos;
              </span><span class='TPXMLkw2'>threadingModel</span>=<span class='TPXMLstr'>&apos;Apartment&apos;
              </span><span class='TPXMLkw2'>progid</span>=<span class='TPXMLstr'>&apos;TCMXML.XMLResponder&apos; </span>/<span class='TPXMLkw1'>&gt;</span>
  <span class='TPXMLkw1'>&lt;</span>/file<span class='TPXMLkw1'>&gt;</span>
<span class='TPXMLkw1'>&lt;</span>/assembly<span class='TPXMLkw1'>&gt;</span>
</pre>
<p>I've saved this as <code>RegistrationFreeCOM.exe.manifest</code> in the same directory as my test application <code>RegistrationFreeCOM.exe</code>, and also copied my fake implementation <code>FakeTCMXML.dll</code> into that directory. The test application will activate <code>TCMXML.XMLResponder</code> from <code>FakeTCMXML.dll</code>, regardless of whether that ProgID already occurs in the registry, and without affecting that registration.</p>
<h3>Creating a manifest file</h3>
<p>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.<br />
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.</p>
]]></content:encoded>
			<wfw:commentRss>http://grootveld.com/archives/16/registration-free-com/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

