Monday, January 15, 2007

Side-by-Side COM Registration Part I

Previously I posted a little bit about Side-By-Side but I have discovered a lot since then. Here is my attempt to share what I’ve discovered with an easy to read easy to understand post step by step tutorial of Side-By-Side. In Part II of the series I will walk you through an example application that will use COM and never touch your registry! How exciting is that?

If you don’t know what Side-by-side, it is a feature in Windows XP, 2003 and Vista (Windows 2000 does not support Side-By-Side) that allows an application to remove their dependency on the windows registry for COM registration and tools such as regasm.exe and regsvr32.exe/tregsvr.exe. This means that Xcopy deployment is now possible while using COM and COM Interop from your application. This is very exciting for those of us who use COM. Those who don’t use COM, well don’t start using it but you could still read this and get a chuckle out of what the rest of use have to deal with. Hopefully I can save you all some time because this stuff ain’t easy.

So here are the 10 easy steps to using Side-By-Side:

1. Start Project1.exe and the loader looks for Project1.exe.manifest

2. The application .manifest file starts with a header:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0";>



Next you specify the name of the module, a few other default things, and a version number that must match the EXE. If there is no version info then the default is 1.0.0.0. Example:


<assemblyIdentity
name="Project1.exe"
version="1.0.0.0"
type="win32"
processorArchitecture="x86"
/>



3. If you reference other modules that are Assemblies then they must have a section with the name of the module, some default things, a version number that must match the DLL and an optional publicKeyToken. Example:


<dependency>
<dependentAssembly>
<assemblyIdentity
name="Test.Server"
version="1.2.3.4"
type="win32"
publicKeyToken="b03a7f5905842b5a"
/>
</dependentAssembly>
</dependency>



Note that if you are delay signing your assemblies you cannot use Side-By-Side. To get the public key string type sn –T Test.Server.dll.

4. If you reference other modules that are COM Servers there must be a section with the DLL name, and GUIDs of all the CoClasses that CoCreateInstance is called with.


<file name="Server.dll">
<comClass clsid="{C7D9C6F6-3D2C-11B2-BBAC-00B05FB17624}"/>
</file>



5. The application manifest then ends with </assembly>

6. Each Assembly that is referenced needs a manifest file and a Win32 manifest resource. The .manifest file is named the assembly file name with the .manifest extension. For Example: Test.Server.dll’s manifest file is named Test.Server.manifest. This is a little confusing since the application manifest includes the .exe extension.

At this point I need to make a special note that if you are running on Windows XP 64-bit or Windows 2003 (and I presume you can include Vista in this list), then you can either have the resource or the .manifest file but both are not required. Windows XP 32-bit on the other hand requires only the manifest resource differing from Windows XP 64-bit. It makes one wonder why the Windows XP 64-bit and 32-bit don’t have the same loader besides the 64-bit part. So if you want your application to work on the lowest common denominator, in this case Windows XP 32-bit, then both the manifest file and the manifest resource are required.

7. The assembly manifest starts with a header:


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0";>



Next you specify the name of the module, some default things, a version number that must match the DLL and an optional publicKeyToken. Example:


<assemblyIdentity
name="Test.Server"
version="1.2.3.4"
type="win32"
publicKeyToken="a91a7c5705831a4f"
/>



Since this Assembly will be used through COM Interop it needs a section to describe the type library:


<file name="Test.Server.tlb">
<typelib
tlbid="{9AE5A349-7CDD-4B99-ABAE-8F4646E194B6}"
version="1.0"
helpdir=""
flags="hasdiskimage"/>
</file>



At this point I want to mention that I highly recommend reading my previous post on Good COM Interop Practices.

8. For each .NET class that you create through COM Interop with CoCreateInstance there must be a section with a namespace and name, GUID, .NET Version and threading model.


<clrClass
name="Test.Server.TFoo"
clsid="{97109D87-BC72-4285-9FF6-C22BCF58B361}"
threadingModel="Both"
runtimeVersion="v2.0.50727"
/>



9. To generate the manifest resource you need a .rc file containing:


#include <winuser.h>
RCDATA RT_MANIFEST "Test.Server.manifest"



You can then run brcc32.exe Test.Server.rc to generate Test.Server.res. To link in the resource with Delphi add {$R Test.Server.res} to the .dpk, with C# and J# use the /win32res option, and ilasm.exe use the /RESOURCE option.

10. The assembly manifest then ends with </assembly>

No comments:

Post a Comment