我正在尝试使用 CoRegisterClassObject 来自定义加载包含 com 对象的 dll 的方式。我正在尝试解决当线程的单元类型与 com 对象不匹配时遇到的问题。我遇到了一个问题,虽然 coregisterclassobject 返回 S_OK,但似乎没有做任何事情,因为 com 对象仍然依赖于要创建的注册表。这是我写的一个示例,作为失败的概念证明(TestComObj 是单元线程)。
LPSTREAM factory_stream = NULL; //GLOBAL VARIABLE FOR TEST
DWORD __stdcall FactoryThread(LPVOID param)
{
CoInitialize(NULL);
CustomClassFactory *factory = new CustomClassFactory();
factory->AddRef();
CoMarshalInterThreadInterfaceInStream(IID_IClassFactory, (IClassFactory*)factory, &factory_stream);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
factory->Release();
CoUninitialize();
return 0;
}
这是我主要功能的相关部分。
CoInitializeEx(NULL, COINIT_MULTITHREADED);
HANDLE regThread = CreateThread(NULL, 0, FactoryThread, NULL, 0, NULL);
Sleep(5000); //ensures that the factory is registered
IClassFactory *factory = NULL;
CoGetInterfaceAndReleaseStream(factory_stream, IID_IClassFactory, (void**)&factory);
DWORD regNum = 0;
HRESULT res = CoRegisterClassObject(clsid, factory, CLSCTX_INPROC_SERVER, REGCLS_MULTI_SEPARATE, ®Num);
//res == S_OK
{
TestComObjLib::ITestComObjPtr ptr;
HRESULT hr = ptr.CreateInstance(__uuidof(TestComObjLib::TestComObjCoClass), NULL);
//hr == E_NOINTERFACE HERE if not registered in the registry
}
CoRevokeClassObject(regNum);
CoUninitialize();
这个想法是,由于注册表不应该与 CoRegisterClassObject 一起使用,我需要在 STA 而不是当前的 MTA 线程中手动创建单元线程对象。我注意到,当不使用 CoRegisterClassObject 时,CoGetClassObject 会产生一个新线程并在该线程中调用 DllGetClassObject,所以我认为只需要在 STA 中创建类工厂,然后对象就会在那里。
我看到的问题是,在上面的代码中,它仍然使用注册表来创建 TestComObj,即使 ClassFactory 行为正常。现在很简单。它只是在正确的 dll 上调用 LoadLibrary,然后调用 dllgetclassobject,并在其结果上调用 createinstance。当不处理单元和线程问题时,我可以使用它来创建 com 对象而无需注册它。所以我不确定这里出了什么问题。