I am writing a Win32 C++ DLL that uses the COM to query WMI. How can I programmatically determine if COM has already been initialized? Thanks.
4 Answers
Mark Ransom is right
the straightforward, clean and simple solution is to require COM initialization by the caller.
Ugly hack
You can try your first call - likely CoCreateInstance
, and if it returns CO_E_NOTINITIALIZED, run CoInitialize
yourself (and don't forget to uninit in that case)
However, it is still problematic to "inject" a CoInitialize into a caller thread from a DLL. So there's a
Clean Solution
Let the DLL create a worker thread (which means the DLL needs Init and Teardown calls), CoInitializeEx in this thread yourself, and move all the COM calls to that separate thread.

- 40,917
- 20
- 104
- 186
-
2Thanks, I ended up using a worker thread. Initialization and tear-down are all done in the same DLL function. `WaitForSingleObject` is used to wait for the worker thread to complete. – Jim Fell Dec 16 '10 at 22:19
The easiest way is not to bother, just make it a requirement of anybody using your DLL that they initialize COM first. Otherwise you run the risk of messing up their own initialization if they perform it after yours.
On the other hand if your flags to CoInitializeEx
match those of the application, you should be fine. From the CoInitializeEx
documentation:
Multiple calls to CoInitializeEx by the same thread are allowed as long as they pass the same concurrency flag, but subsequent valid calls return S_FALSE.

- 299,747
- 42
- 398
- 622
-
That is really not helpful. Unfortunately, most of the application is already written. I need to know how to determine if the COM has already been initialized. I realize this is not best practice, but it's what have to work with. – Jim Fell Dec 15 '10 at 22:54
-
@Jim: This is right. Just always CoInitializeEx() exactly once and CoUninitialize() exactly once in your code. It doesn't and shouldn't matter if it has already been called in your thread. Besides which, you don't control when the code you downt control will un-init COM, so relying on the initialization state when you start up is dangerous. – John Dibling Dec 15 '10 at 23:11
-
+1, Also see this: http://stackoverflow.com/q/2154151/57428 - looks like calling `CoInitialize()` more that once can lead to some weird problems. – sharptooth Dec 16 '10 at 04:43
It follows @peterchen clean solution as I coded it for a thread-safe COM logger component that I wanted to wrap:
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);
}

- 14,736
- 5
- 58
- 73
CoInitializeEx\CoUninitialize should only be called by threads (not by Dll-calls).
BTW ,you should not Use CoInitializeEx\CoUninitialize in DllMain !

- 3,980
- 1
- 14
- 25