我正在尝试使用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对象而不进行注册。所以我不确定这里出了什么问题。