Wednesday, September 3, 2008

Registration Free COM for .net/managed components

.NET assemblies can be used from native code via COM.  Unfortunately COM, by default, uses the shared assembly model.  That is, everyone using a given version of a COM server uses the executable (or dll) stored in the same place.  So the last app to install the COM component determines which COM executable is used; if that app is uninstalled all the other apps that depended on that component are broken.

To get around this problem Registration Free COM was introduced.  Now that computers have so much memory one of the main benefits of shared assemblies/shared dlls is no longer relevant.  And the problem of DLL hell is much mitigated when every application has it's own copy of the DLLs it uses.

The excellent article "Registration-Free Activation of .NET-Based Components: A Walkthrough" got me about 3/4ths of the way there but I didn't like having to manually compile a project so as to embed the .net component's manifest as a native win32 resource in the resulting executable.

Fortunately, another blog post "How to embed a manifest in an assembly: Let Me Count The Ways..." points out how to use the manifest tool (mt.exe) included in the 2.0 SDK and vs2005 to embed the resource after the assembly has been built (e.g., a post build event).

I got this working on a small test project.  The key components were as follows:

Native application manifest:

<?xml
version="1.0"
encoding="utf-8"?>
<assembly
xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="CppClient" version="1.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="RegFreeCSharpClassLibrary"

version="1.0.0.0"/>

</dependentAssembly>
</dependency>
</assembly>








This should be added to the generated manifest via Project Properties -> Manifest Tool -> Input and Output -> Additional Manifest Files.  Be sure not to name it with the .manifest extension until you've verified that it work; visual studio 2005 always includes any files in the project that end with the .manifest extension.





NOTE:  Since I'm using Windows XP I couldn't get the native application manifest to work when it was embedded in the executable but it works as a standalone .exe.manifest file alongside the executable.





For the managed component that was being exposed via COM, the manifest was as follows:




<?xml
version="1.0"
encoding="UTF-8" standalone="yes"?>

<assembly
xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="RegFreeCSharpClassLibrary"
version="1.0.0.0" />
<clrClass clsid="{684DFB01-D74F-41c7-95F9-6520C910BF18}" name="RegFreeCSharpClassLibrary.MyClass"></clrClass>
</assembly>






This manifest needs to be converted into a binary win32 resource then embedded into the resulting executable via the manifest tool mt.  In a post build event this can be done as follows:





mt.exe" -manifest "$(ProjectDir)$(TargetName).manifest"  –outputresource:"$(TargetPath)";#1


No comments :

Post a Comment