Registration-free COM client

Thalamus via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Wed Jun 29 07:51:10 PDT 2016


On Tuesday, 28 June 2016 at 02:30:56 UTC, thedeemon wrote:
> To load load a COM object from a given file (DLL or AX) without 
> having it registered, just load the file with CoLoadLibrary() 
> and use its DllGetClassObject() function to get IClassFactory 
> which will give you any kind of object in this library.
> Here's how I do it (in my case the requested object has 
> "IBaseFilter" COM interface):

Thanks to both of you!

I was hoping there would be a code-only solution, and I'm glad to 
see one is possible. It isn't quite working for me yet, though. I 
can get the HINSTANCE in the CoLoadLibrary call, but 
GetProcAddress for DllGetClassObject fails, with 
ERROR_PROC_NOT_FOUND.

I've never written a COM server before (only clients), so I must 
be building the C# assembly incorrectly. I'm just not sure how. 
Everything across the board is built as 64-bit, and I've selected 
"Register for COM interop". The C# is pretty simple:

[ComVisible(true)]
[Guid("B99B6E64-966C-4655-B633-D0108F4DE909")]
public interface ITestInterface
{
     int Identifier();
}

[ComVisible(true)]
[Guid("0F8BDA67-D6CF-42D0-A62D-E19BD7864362")]
[ClassInterface(ClassInterfaceType.None)]
public class TestClass : ITestInterface
{
     public int Identifier()
     {
         return 42;
     }
}

and the D code (mostly unchanged from your example):

interface ITestInterface
{
     int Identifier();
}


ITestInterface GetInstance()
{
     import std.exception;
     import core.sys.windows.com;
     GUID iid = { 0xB99B6E64, 0x966C, 0x4655, [0xB6, 0x33, 0xD0, 
0x10, 0x8F, 0x4D, 0xE9, 0x09]};
     GUID clsid = { 0x0F8BDA67, 0xD6CF, 0x42D0, [0xA6, 0x2D, 0xE1, 
0x9B, 0xD7, 0x86, 0x43, 0x62]};

     HINSTANCE hinst = 
CoLoadLibrary(cast(wchar*)r"managed\bin\test.dll".toUTF16z, 0); 
//CoFreeLibrary will need to be called later.
     enforce!COMException(hinst);

     LPFNGETCLASSOBJECT fnGetClassObject = 
cast(LPFNGETCLASSOBJECT)GetProcAddress(hinst, 
"DllGetClassObject");
     enforce!COMException(fnGetClassObject);

     IClassFactory factory;
     auto factory_iid = IID_IClassFactory;
     fnGetClassObject(&clsid, &factory_iid, 
cast(void**)&factory).checkHR("fnGetClassObject failed");
     enforce!COMException(factory);

     ITestInterface instance;
     factory.CreateInstance(null, &iid, 
cast(void**)&instance).checkHR("factory.CreateInstance");
     return instance;
}

Any ideas what I'm missing?

thanks!
Gene


More information about the Digitalmars-d-learn mailing list