我在写一个使用COM来查询WMI的Win32 C++ DLL。如何以编程方式确定COM是否已被初始化?谢谢。COM初始化和在Win32 C++ DLL中的使用
回答
马克赎金是正确
的简单,干净和简单的解决方案是通过调用者需要COM初始化。
丑陋的黑客
你可以试试你的第一个电话 - 可能CoCreateInstance
,如果返回CO_E_NOTINITIALIZED,自己运行CoInitialize
(不要忘记在这种情况下,以UNINIT)
然而,它将CoInitialize“注入”DLL中的调用者线程仍然存在问题。所以这是一个
清理解决方案
让DLL创建工作线程(这意味着该DLL需要初始化和拆卸电话)的CoInitializeEx在此线程自己,把所有的COM调用到单独的线程。
最简单的方法是不要打扰,只是让它成为任何人使用你的DLL的要求,他们首先初始化COM。否则,如果他们在之后执行之后就会冒着搞乱自己的初始化的风险。
另一方面,如果您的标记为CoInitializeEx
与应用程序的标记相匹配,则应该没问题。从CoInitializeEx
documentation:由 同一个线程
多次调用的CoInitializeEx被允许,只要 他们通过相同的并发标志, 但后续的有效来电返回 S_FALSE。
这真的是没有帮助的。不幸的是,大部分应用程序已经写好了。我需要知道如何确定COM是否已经初始化。我意识到这不是最佳实践,但它是必须与之合作的。 – 2010-12-15 22:54:24
@Jim:这是对的。在你的代码中,只需要一次CoInitializeEx()和CoUninitialize()一次。它不是也不应该在你的线程中调用它。除此之外,您不控制何时您控制的代码将取消初始化COM,因此启动时依赖初始化状态是危险的。 – 2010-12-15 23:11:48
+1,另请参阅:http://stackoverflow.com/q/2154151/57428 - 看起来像调用'CoInitialize()'更多,一旦可以导致一些奇怪的问题。 – sharptooth 2010-12-16 04:43:00
CoInitializeEx \ CoUninitialize只能由线程调用(不能由Dll调用)。
顺便说一句,你不应该在DllMain中使用CoInitializeEx \ CoUninitialize!
它遵循我编码它线程安全的COM组件记录器,我想换peterchen干净的解决方案:
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);
}
- 1. 在c#项目中初始化64位Com C++ dll
- 2. Win32服务中的WMI(COM初始化错误)
- 3. 在C中使用COM dll#
- 4. 使用在C#中使用COM的DLL
- 5. 为多个COM操作初始化COM
- 6. C++应用程序无法初始化(0xc0000005),当使用C#DLL
- 7. C++ COM,Direct2D,Win32和WM_CLOSE
- 8. C++:在初始化列表中初始化对ofstream的引用
- 9. COM DLL的C + + dll
- 10. 在C++中使用COM对象dll
- 11. 在C#项目中使用COM dll
- 12. 初始化在C++
- 13. COM初始化错误0x80040154加载c#COM对象与c + +程序
- 14. 联盟初始化++和C
- 15. 初始化在C++
- 16. 初始化在C++
- 17. 初始化引用和变量在C++
- 18. 初始化一个DLL
- 19. 一次Hook DLL初始化
- 20. dll初始化方法
- 21. 在VC++中使用COM DLL dll
- 22. 初始化在C++
- 23. 在C++中初始化类
- 24. 在C#中初始化Var#
- 25. 初始化,初始化与参数和便利初始化
- 26. 在C++中使用&&的声明和初始化
- 27. 用于在C++中初始化的memset
- 28. C++ - 初始化与骨料初始化
- 29. 在FSI中使用COM DLL
- 30. 初始化列表和C++
谢谢,我结束了使用工作线程。初始化和拆除都在同一个DLL函数中完成。 'WaitForSingleObject'用于等待工作线程完成。 – 2010-12-16 22:19:36