Wednesday 19 August 2009

Registration Free COM

From Windows XP SP2 Microsoft introduced a feature called RegFree COM, which allows you to call COM objects (yes some of us still use COM) without needing to register them first. The object in question must be in the same folder as the caller but this makes it much easier to install these objects and goes a little way to the xcopy distribution utopia. To use RegFree COM your caller and callee assemblies needs to have manifest files either externally or embedded - Manifest Files Reference. The assemblies can be written in any language that supports COM and you can call between languages, e.g. vb to vb, vb to .Net, .Net to vb.

The calling application needs a manifest file configured as follows, in this example the application is called MyApp.exe so the manifest is MyApp.exe.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="MyApp" version="0.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="ComAssembly.dll" version="1.2.3.4" />
</dependentAssembly>
</dependency>
</assembly>

The COM assembly needs a manifest file configured as follows, in this example the assembly is called ComAssembly.dll so the manifest is ComAssembly.dll.manifest:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="ComAssembly.dll" version="1.2.3.4" />
<file name="ComAssembly.dll">
<comClass clsid="{11111111-2222-3333-4444-555555555555}" threadingModel="Both" />
</file>
</assembly>

In MyApp.exe.manifest I have set the version to “0.0.0.0” this should really match the application version but “0.0.0.0” works. The dependentAssembly/assemblyIdentity  can be repeated for as many COM dependencies that you have.

The assemblyIdentity in the caller manifest must match exactly the one in the callee.

Getting this right can be quite difficult to debug, on XP the only clues to problems are written to the system eventlog with the source SideBySide. On Vista (and I assume Windows 7 and Windows Server 2008 although I haven’t tried it) you can use SxsTrace to help debug the problem. To start trace run “SxsTrace Trace -logfile:SxsTrace.etl” to convert the log file to something you can view run “SxsTrace Parse -logfile:SxsTrace.etl -outfile:SxsTrace.txt”.

The two manifest files presented here have been reduced to the minimum required to get the code to work, they are more settings that can be included see the Manifest Files Reference for more details.

See also:

17 comments:

Christopher Painter said...

I heard about this 5 years ago but dismissed it because of all the W2K systems I still had to support.

The other day this topic came up because some developer wanted to add 100+ COM DLL's to his install and I cringed at the risk and complexity.

I suggested COM Free Reg but it was shot down because the developer didn't want to take on the responsibility of generating the manifest files.

I then asked the developer if he really needed all 100 DLL's or only a handful. I was told that he didn't know but that the product needed to ship in a couple of days and he didn't have time to find out.

Oh the joy...

Neil Sleightholm said...

I am using this quite a bit now but nothing like 100 DLLs! I think the manifest files can be auto generated fairly easily as they don't need much meta data from the DLL. For .Net COM components I embed the manifest in the assembly as it makes it easier to manage.

Christopher Painter said...

Sadly these were third party runtime dll's from LEADTOOLs. If you look at their deployment instructions it's literally from the 1990's.

They don't give a prereq instaler, MSI or MSM. They just give you a ZIP file with the instructions to deploy them to System32 and use RegSvr32 to register them.

Pally Sandher said...

I'm so going to implement this for our next major release.
Being able to push some of the installation headaches over to the rest of the development team might make them more aware of the problems they cause.
If it saves me having to run the COM exposed DLL's through heat.exe everytime there's a version number change I'm all for it.

Anonymous said...

hi, just a few weeks ago I inherited some old code that is heavily vb6/C++ com based. One of the first thing that I would like to do is to get rid of "dll hell" that users are having with the system. Side by Side approach seems what I need and it is working fine using Windows XP. How does it play with Windows 10, regardless what I do i always get "class not registered".
the registering dll works but side by side using manifest does not.

Unknown said...

hi, just a few weeks ago I inherited some old code that is heavily vb6/C++ com based. One of the first thing that I would like to do is to get rid of "dll hell" that users are having with the system. Side by Side approach seems what I need and it is working fine using Windows XP. How does it play with Windows 10, regardless what I do i always get "class not registered".
the registering dll works but side by side using manifest does not.

Neil Sleightholm said...

I am using on Windows 10 without any issues. All machine DLL's are 32 bit if that makes a difference.

Anonymous said...

Neil,

Thank you for a quick response.

I used the exact same sample that this article provides (as an MSI file)

https://msdn.microsoft.com/library/ms973913.aspx?f=255&MSPPError=-2147217396#rfacomwalk_topic7

plus added required msvcr71.dll to it.

Windows xp - works great, windows 10 - 64 bit does not.

what did you mean by machine dll;s are 32 bit?


Thank you
Mark


Neil Sleightholm said...

:-) typed to quickly. All my DLL's are 32 bit.

Neil Sleightholm said...

You can try using SxsTrace to see if that identifies the issue. This is the sequence I use:
del SxsTrace.*
SxsTrace Trace -logfile:SxsTrace.etl
SxsTrace Parse -logfile:SxsTrace.etl -outfile:SxsTrace.txt

Anonymous said...

thank you

I think you may be correct in saying "system's dll" ;~)

I have 2 virtual Windows 10 installations. One of them (I just checked) works and the other is not, so it must be related to path and using 64 vs. 32 bits dlls.

The trace file for some reason is always empty

Neil Sleightholm said...

I think you need to run it elevated (it's been a while since I have used it).

Anonymous said...

ok, here is what I see.
1. all works good using w10
2. rename manifest file just to see if it is going to fail. It does work. failing
3. rename it back - still broken


so after renaming manifest and then renaming it back things stop working.

going to play with it more....

and yes, elevated seems the issue. get some traces there but did not see anything yet related to my problem

thank you again

Anonymous said...

Neil,


here is what I get as traces, do you see anything wrong there?
this looks ok to me.

thank you
mark




=================
Begin Activation Context Generation.
Input Parameter:
Flags = 0
ProcessorArchitecture = AMD64
CultureFallBacks = en-US;en
ManifestPath = C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\client.exe.Manifest
AssemblyDirectory = C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\
Application Config File =
-----------------
INFO: Parsing Manifest File C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\client.exe.Manifest.
INFO: Manifest Definition Identity is client,type="win32",version="1.0.0.0".
INFO: Reference: SideBySide.X,type="win32",version="1.0.0.0"
INFO: Resolving reference SideBySide.X,type="win32",version="1.0.0.0".
INFO: Resolving reference for ProcessorArchitecture SideBySide.X,type="win32",version="1.0.0.0".
INFO: Resolving reference for culture Neutral.
INFO: Applying Binding Policy.
INFO: No binding policy redirect found.
INFO: Begin assembly probing.
INFO: Did not find the assembly in WinSxS.
INFO: Attempt to probe manifest at C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\SideBySide.X.DLL.
INFO: Attempt to probe manifest at C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\SideBySide.X.MANIFEST.
INFO: Manifest found at C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\SideBySide.X.MANIFEST.
INFO: End assembly probing.
INFO: Resolving reference SideBySide.X.mui,language="*",type="win32",version="1.0.0.0".
INFO: Resolving reference for ProcessorArchitecture SideBySide.X.mui,language="*",type="win32",version="1.0.0.0".
INFO: Resolving reference for culture en-US.
INFO: Applying Binding Policy.
INFO: No binding policy redirect found.
INFO: Begin assembly probing.
INFO: Did not find the assembly in WinSxS.
INFO: Did not find manifest for culture en-US.
INFO: End assembly probing.
INFO: Resolving reference for culture en.
INFO: Applying Binding Policy.
INFO: No binding policy redirect found.
INFO: Begin assembly probing.
INFO: Did not find the assembly in WinSxS.
INFO: Did not find manifest for culture en.
INFO: End assembly probing.
INFO: Parsing Manifest File C:\Users\Mark Belfer\Desktop\Registration-Free Activation of COM-Based Components\deployed\SideBySide.X.MANIFEST.
INFO: Manifest Definition Identity is SideBySide.X,type="win32",version="1.0.0.0".
INFO: Activation Context generation succeeded.
End Activation Context Generation.

Neil Sleightholm said...

That looks ok to me - assuming your is version 1.0.0.0.

Anonymous said...

ok, finally found figured out with the help of reading this article

http://superuser.com/questions/10426/windows-equivalent-of-the-linux-command-touch

basically SxS Activation Context Cache caches .manifest files and the only way to get it refresh is by changing datetime stamp on executable.

Worked great!

Thank you for your help



Neil Sleightholm said...

Wow good find, never knew that.