September 05, 2006
Would you like some MSIL with your COM ?
I described last time my dilemma in trying to get a COM component to work with my nice little XCOPY deployed .NET 2.0 application. That is, without registering the COM component beforehand. The smarties among you out there probably jumped up and said "Whoa! I can do that with the nifty .NET 2.0 Registry-less COM deployment technology". Yes, you're totally correct - I could have just specified a manifest for my COM component and away I go.
Just one problem though.
It doesn't work on anything less than Windows XP SP2. That rules out Windows 2000, NT and any of the Windows 9x series. In my case, I don't need to worry anymore about NT and the 9x series (hooya!) but I still do need to worry about Windows 2000 - approximately 20% of our customers still use it although the number shrinks slowly every quarter. So I need a solution that is guaranteed to work, not mostly, kinda work.
Now to the solution.
One of the things that strikes me about software development nowadays compared to times past is that we rarely need to dive down and program close to the "metal" or in this case the "CLR". I mean how many of you, honestly, ever cracked open a tome on MSIL and read the instruction set let alone wrote any code with it? Hmmm. Don't see a lot of hands out there. Mine is certainly not one of them.
But in this case, a little low-level MSIL was what I needed. Without further delay, here's the code that registers any COM component given a IntPtr value from a Native Interop call to the Windows function GetProcAddress:
.assembly extern mscorlib {}
.assembly ComSupport {}
.namespace MyCompany.MsIlTools
{
.class public ComSupport
{
.method public static void Register(native int pfn)
{
.maxstack 1
ldarg.0 // Push pfn onto the execution stack
calli unmanaged stdcall void()
ret
}
}
}
Wow! For a low-level language, that's pretty readable even if you've never tinkered much with MSIL. Looks pretty much like a C# static function that takes a function pointer (even though C# doesn't support function pointers) and calls it as an unmanaged bit of code. Since we know DllRegisterServer (the entry point into a DLL to register it) takes no parameters, the setup and call to the function pointer is trivial.
To use this code, you drop it into a .IL file, compile it with ILASM.EXE to an assembly and add the assembly to your project. Then call the "Register" function just as you would any C# static function in a class.
Nice.
Posted by Mark M. Baker at 10:40 PM Permalink
|