我正在写一个Win32 C++ DLL,它使用COM来查询WMI。我如何通过编程来确定COM是否已经初始化?谢谢。
4bbkushb1#
"马克·兰塞姆说得对"直接、干净和简单的解决方案是要求调用方进行COM初始化。"丑陋的黑客"您可以尝试第一次调用-可能是CoCreateInstance,如果它返回CO_E_NOTINITIALIZED,则自己运行CoInitialize(在这种情况下不要忘记取消初始化)
CoCreateInstance
CoInitialize
让DLL创建一个辅助线程(这意味着DLL需要Init和Teardown调用),您自己在此线程中使用CoInitializeEx,并将所有COM调用移到该单独的线程。
wqsoz72f2#
最简单的方法是不麻烦,只要要求任何使用你的DLL的人先初始化COM。否则,如果他们在你的初始化之后执行,你就有可能搞砸他们自己的初始化。另一方面,如果CoInitializeEx的标志与应用程序的标志相匹配,则应该没有问题。允许同一线程多次调用CoInitializeEx,只要它们传递相同的并发标志即可,但后续有效调用返回S_FALSE。
CoInitializeEx
lhcgjxsq3#
它遵循@peterchen clean solution,因为我为一个线程安全的COM日志记录器组件编写了它,我想 Package 它:
IComLoggerPtr _logger; _bstr_t _name; HANDLE _thread; HANDLE _completed; Logger::Logger(_bstr_t name) { _name = name; _completed = ::CreateEvent(NULL, false, false, NULL); if (_completed == NULL) ::AtlThrowLastWin32(); // Launch the thread for COM interation DWORD threadId; _thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(this->threadRun), (LPVOID)this, 0, &threadId); // Wait object initialization HRESULT hr = ::WaitForSingleObject(_completed, INFINITE); if (FAILED(hr)) AtlThrow(hr); } Logger::~Logger() { ::SetEvent(_completed); CloseHandle(_thread); CloseHandle(_completed); } DWORD WINAPI Logger::threadRun(LPVOID opaque) { Logger *obj = (Logger *)opaque; // Init Free-Threaded COM subsystem HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); if (FAILED(hr)) ::AtlThrow(hr); hr = obj->_logger.CreateInstance(__uuidof(ComLogger)); if (FAILED(hr)) ::AtlThrow(hr); obj->_logger->Init(obj->_name); // Initialization completed bool success = ::SetEvent(obj->_completed); if (!success) ::AtlThrowLastWin32(); // Wait release event hr = ::WaitForSingleObject(obj->_completed, INFINITE); if (FAILED(hr)) AtlThrow(hr); obj->_logger.Release(); // Release COM subsystem ::CoUninitialize(); } HRESULT Logger::Log(_bstr_t description) { return _logger->Log(description); }
bxjv4tth4#
CoInitializeEx\CoUninitialize只能由线程调用(不能由Dll调用调用)。顺便说一句,您不应该在DllMain中使用CoInitializeEx\CoUninitialize!
4条答案
按热度按时间4bbkushb1#
"马克·兰塞姆说得对"
直接、干净和简单的解决方案是要求调用方进行COM初始化。
"丑陋的黑客"
您可以尝试第一次调用-可能是
CoCreateInstance
,如果它返回CO_E_NOTINITIALIZED,则自己运行CoInitialize
(在这种情况下不要忘记取消初始化)清洁溶液
让DLL创建一个辅助线程(这意味着DLL需要Init和Teardown调用),您自己在此线程中使用CoInitializeEx,并将所有COM调用移到该单独的线程。
wqsoz72f2#
最简单的方法是不麻烦,只要要求任何使用你的DLL的人先初始化COM。否则,如果他们在你的初始化之后执行,你就有可能搞砸他们自己的初始化。
另一方面,如果
CoInitializeEx
的标志与应用程序的标志相匹配,则应该没有问题。允许同一线程多次调用CoInitializeEx,只要它们传递相同的并发标志即可,但后续有效调用返回S_FALSE。
lhcgjxsq3#
它遵循@peterchen clean solution,因为我为一个线程安全的COM日志记录器组件编写了它,我想 Package 它:
bxjv4tth4#
CoInitializeEx\CoUninitialize只能由线程调用(不能由Dll调用调用)。
顺便说一句,您不应该在DllMain中使用CoInitializeEx\CoUninitialize!