Registration Free COM Interop Deployment

Today I ran two rounds of deployment of to our production servers. This led me to start pondering a blog post on the strategy we've chosen to make this as painless as possible.

Our operational requirements demands that deployment of new versions is done continuously, without downtime, while our users are actively using the software.
As long as the deployment environment is controlled, .net applications can be xcopied directly, with no extra steps. But our application is a mix of .net and legacy VB6 components. This mix would lead many to believe that registration in the registry is unavoidable, which could lead to DLL hell.

But there is a solution:

Registration free deployment

Most resources on the net approach registration free (RegFree) deployment from the .net side. Meaning that a .net application consumes legacy dll components.
Our scenario is the other way around, we have a VB6 based application that consumes a number of .net libraries.

Manifests

RegFree deployment is all about manifest files. Manifests are xml files that does the job of the registry, telling the consuming application where it can find required libraries.

There are some, but not too many resources around to help you get your head around how to create manifests, most notably Registration-Free Activation of COM Components: A Walkthrough by Steve White and Leslie Muller on MSDN. The problem I found was that most of the articles I managed to dig up (and quite a bit of digging was required) was just to complicated and thorough as they tried to cover all aspects of the technology at once. There was none that I can think of that managed to clearly cover the basics you needed to get started. The walkthrough refered to above seems simple enough, but using that I was not able to get my application to run (though this might just be me not understanding simple stuff).
Also building manifests by hand as a tedious task, requiring much boilerplate work.
So i went looking for:

The easy way out

An instructor on a course once told me that no matter what task you want to accomplish, someone has build a tool to make it easier. And once again this is true. There are at least two tools that I know of:

  • Genman32 by Junfeng Zhang of Microsoft is a command line tool for generating manifest files. I never really got this one to work for my requirements, but it might work out for other people with different requirements.
  • Side-by-Side Manifest Maker by Maze Computer Communications is the tool I ended up using.
    It's really simple to use. Just drag in the application executable and all required libraries, and press the button. All manifests and typelibs are created and placed in directories as needed. The whole package is then ready for xcopy deployment.

Now that I had RegFree deployment actually working I set out to figure out what I was missing when I tried hand rolling manifests.

The basic needs

The Manifest makers online help is actually one of the best resources I have found to help understanding the concepts and structures behind RegFree deployment. With help from that and my working set of manifests I got a fairly good understanding of what is actually needed to get up and going.

The assembly manifest

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

<assemblyIdentity
 name="Three.Part.Identifier"
 version="1.0.0.0"
 type="win32"
 processorArchitecture="x86"
/>

</assembly>

The assembly manifest is refered by the application manifest. This is the one manifest that I have never really gotten my head around, but I have come to believe that it has something to do with isolating applications, and making sure the application does not go looking in the registry for libraries. Any further info on this manifest will be greatly appreciated.
The naming convention for the assembly manifest is Three.Part.Identifier.manifest

The application manifest

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

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

<dependency>
 <dependentAssembly>
  <assemblyIdentity
   name="NameOf,NetLibrary"
   version="1.0.0.0"
   type="win32"/>
 </dependentAssembly>
</dependency>

<dependency>
 <dependentAssembly>
  <assemblyIdentity
   name="Three.Part.Identifier"
   version="1.0.0.0"
   type="win32"
   processorArchitecture="x86"/>
 </dependentAssembly>
</dependency>

</assembly>

The application assembly identifies the application and describes what libraries it depends on.
Naming convention for the application manifest is application.exe.manifest

The "Library" manifest

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

<assemblyIdentity
 name="NameOf.NetLibrary"
 version="1.0.0.0" '
 type="win32"
/>

<clrClass
  name="Class.name"
  clsid="{GuidForClass}"
  progid="Fhd.Fhd"
  threadingModel="Both"
  runtimeVersion="v4.0.30319"
/>

<file name="Typelib.tlb">
 <typelib
    tlbid="{GuidForTypeLib}"
    version="1.0"
    helpdir=""
    flags="hasdiskimage"/>
</file>

</assembly>

The "library" manifest identifies the library for the RegFree process and defines which classes are available, and which file to look in to find these classes. Being an interop project this manifest references the Typelib (.tlb) file generated for my .net library. This is part of what is required for COM to use .net libraries, and will probably be covered in another blog post.

Note the runtimeVersion attribute on the clrClass element. This is only required if you target .net 4.
For some reason the .net runtime will use the highest version available before .net4 when initialized from a manifest. If you need .net 4 you have to specify this in the manifest
(Took me quite a while wading through less than informative error codes to figure that out)
Note: As of writing this, the Manifest maker software does not recognize .net 4 runtime, and the attribute have to be added manually before deployment. But they have promised to fix this in a soon-to-come update

Naming convention for the library manifests is libraryname.manifest

The last thing to be aware of is where all these manifests and libraries are placed in relation to each other.

Relative placement of files

Due to the way the .net runtime works, where the files are placed in relation to the manifests and the applications makes a difference.
The runtime searches first in the subdirectories of the directory where the manifest files of the required libraries is placed then it goes to the Global Assembly Cache (GAC). The type libraries (.tlb) of the .net files on the other hand needs to be in the same directory as the manifest files.
It is however possible to embed the manifest as a resource in the .net dll file. If this is done it is not necessary to place the .net dlls in subdirectories. The Manifest maker software can do this for you, or you can make it a part of your build process. (This process I believe is described in the walktrough referred earlier.)
Manifest files needs to be in the same directory as the executable, with one exception. The assembly manifest, which is placed in a subdirectory named with the Three.Part.Identifier (one more strange thing with that manifest.)
That summary came out a bit messy, but I'll try to clarify with som ASCII art:

|[Library]
| |_Library.dll
|
|
[Three.Part.Identifier]
| |_Three.Part.Identifier.manifest
|
|_Application.exe
|_Application.exe.manifest
|_Library.manifest
|_Library.tlb

That's it

RegFree deployment, in particular when dealing with com interop (it can also be utilized for pure .net scenarios) makes my life (and my sysadmins life) a a whole lot easier though it can seem bit daunting at first.

Categories: