0

我正在尝试使用 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, &regNum);
//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 对象而无需注册它。所以我不确定这里出了什么问题。

4

0 回答 0