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