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

Reply via email to