Estoy escribiendo una DLL Win32 C++ que utiliza el COM para consultar WMI. ¿Cómo puedo determinar mediante programación si COM ya se ha inicializado? Gracias.Inicialización de COM y uso en Win32 C++ DLL
Respuesta
Marcos Ransom es correcto
la solución fácil, limpio y sencillo es exigir inicialización COM por la persona que llama.
Rutina fea
Puede probar su primera llamada - CoCreateInstance
probable, y si devuelve CO_E_NOTINITIALIZED, ejecute CoInitialize
a sí mismo (y no se olvide de UNINIT en ese caso)
Sin embargo, se sigue siendo problemático para "inyectar" una Coinicialización en un hilo de llamada de una DLL. Así que hay una
Limpiar solución
Vamos a la DLL crear un subproceso de trabajo (lo que significa que el DLL necesita Init y llamadas tearDown), CoInitializeEx en este hilo del mismo, y mover todos los COM llama a ese hilo separado.
La manera más fácil es no molestarse, simplemente haga que todo el que use su DLL inicialice primero COM. De lo contrario, se corre el riesgo de arruinar su propia inicialización si lo realizan después de.
Por otro lado, si sus banderas a CoInitializeEx
coinciden con las de la aplicación, debería estar bien. De los CoInitializeEx
documentation:
múltiples llamadas a CoInitializeEx por el mismo hilo están permitidos siempre y cuando pasan la misma bandera de concurrencia, pero llamadas válidas posteriores volver S_FALSE.
Eso no es realmente útil. Desafortunadamente, la mayoría de la aplicación ya está escrita. Necesito saber cómo determinar si el COM ya se ha inicializado. Me doy cuenta de que esto no es una buena práctica, pero es con lo que tengo que trabajar. –
@Jim: esto es correcto. Simplemente siempre CoInitializeEx() exactamente una vez y CoUninitialize() exactamente una vez en su código. No importa ni debería importar si ya ha sido invocado en su hilo. Además de eso, usted no controla cuando el código que bajó el control desactivará COM, por lo que depender del estado de inicialización cuando arranque es peligroso. –
+1, También vea esto: http://stackoverflow.com/q/2154151/57428 - Parece que se llama a 'CoInitialize()' más de lo que una vez puede ocasionar algunos problemas extraños. – sharptooth
CoInitializeEx \ CoUninitialize solo debe invocarse mediante subprocesos (no mediante llamadas Dll).
Por cierto, no debe utilizar CoInitializeEx \ CoUninitialize en DllMain!
De ello se deduce solución Peterchen limpio como codifiqué por un componente COM registrador de flujos seguros que quería envolver:
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# COM DLL: ¿uso Regasm o Regsvr32?
- 2. Registro Com y dll manifiestos
- 3. Legacy VB6 COM + DLL invocando DLL Win32 nativo - ¿problemas de subprocesamiento con STA?
- 4. Tlbexp.exe en un DLL COM
- 5. Importar una DLL con C++ (Win32)
- 6. registrando com dll en wix
- 7. La diferencia entre DLL tradicional y COM DLL
- 8. Registre un dll COM de C#/VB.NET programáticamente
- 9. ¿Cómo se registra un archivo DLL COM Win32 en WiX 3?
- 10. ¿Cómo puedo detectar el tipo de un dll? (COM, .NET, WIN32)
- 11. ¿Cómo registro una DLL COM escrita en C# con Regsvr32?
- 12. Cómo usar COM dll en mi programa C++
- 13. ¿Qué es "mejor": DLL COM o DLL estándar con Typelib?
- 14. Analizando archivo Win32 PE simple (Exe/DLL) en .NET
- 15. C++ Dll en Dependency walker muestra IESHIMS.dll y MSVCR110.dll
- 16. Cómo llamar a una DLL .NET desde un proceso Win32?
- 17. inicialización Unión en C++ y C
- 18. Haciendo que una DLL COM esté accesible
- 19. DLL COM de legado de 32 bits en Windows Azure
- 20. Cómo creo una DLL de Win32 sin una dependencia en el tiempo de ejecución de C
- 21. Python26, Win32, Zbar - ImportError: carga DLL fallidos
- 22. El registro de un DLL COM NET durante Wix Instalar
- 23. clase de C++ DLL en C# Aplicación
- 24. ¿Cómo escribir y enviar texto a mIRC en C#/Win32?
- 25. ¿Puede NuGet distribuir un dll COM?
- 26. Uso de dll de C++ administrado desde C#
- 27. ¿Cómo se crea una DLL COM en Visual Studio 2008?
- 28. Diferencia entre "COM" tradicional y COM + (en servicios de componentes)
- 29. Uso de una DLL con el encabezado .h en C++
- 30. ¿Cargar un dll COM en el tiempo de ejecución?
Gracias, terminé usando un hilo de trabajo. La inicialización y el desmontaje se realizan en la misma función DLL. 'WaitForSingleObject' se usa para esperar a que se complete el hilo de trabajo. –