Descargar un proveedor
Una vez finalizada la WMI con un proveedor, descarga el proveedor de la memoria. La razón principal por la que WMI descarga un proveedor es conservar los recursos del sistema. Por lo tanto, debe agregar código que permita a WMI descargar el proveedor de forma eficaz. Se tarda en cualquier parte del intervalo especificado en el control de caché al doble de ese intervalo para que WMI descargue un proveedor.
WMI descarga un proveedor de una de las siguientes maneras:
- Descargue un proveedor después de que el proveedor finalice las tareas que se le han dado.
- Descargue rápidamente todos los proveedores cuando el usuario cierre el sistema. Tenga en cuenta que WMI descarga proveedores en proceso cuando el servicio WMI se apaga desde la línea de comandos.
Aunque el primer escenario es más común, debe escribir el proveedor para ambas posibilidades.
En este tema se describen las secciones siguientes:
- Descargar un proveedor inactivo
- Acceso al tiempo de inactividad de un proveedor
- Descargar un proveedor que también es un cliente WMI
- Descargar un proveedor durante el apagado
- Temas relacionados
Descargar un proveedor inactivo
WMI realiza las siguientes acciones cuando descarga un proveedor inactivo:
Determina si el proveedor está inactivo.
WMI usa la propiedad ClearAfter para determinar cuánto tiempo puede permanecer inactivo un proveedor antes de descargar ese proveedor. Para obtener más información, consulte Acceso al tiempo de inactividad de un proveedor.
Llama al método Release del proveedor.
Si el proveedor era un proveedor puro, Release quita completamente el proveedor de la memoria activa. Sin embargo, un proveedor que no sea depure puede seguir ejecutándose después de la versión de llamadas WMI.
Acceso al tiempo de inactividad de un proveedor
La cantidad mínima de tiempo que un proveedor permanece activo viene determinada por la propiedad ClearAfter . Puede encontrar ClearAfter en instancias de clases derivadas de la clase del sistema WMI __CacheControl en el espacio de nombres \root.
En la lista siguiente se describen las clases derivadas de __CacheControl, que controla la descarga del proveedor:
- __EventConsumerProviderCacheControl
- __EventProviderCacheControl
- __EventSinkCacheControl
- __ObjectProviderCacheControl
- __PropertyProviderCacheControl
Puede cambiar la cantidad mínima de tiempo que WMI permite que un proveedor permanezca inactivo editando la propiedad ClearAfter en la instancia de control de caché para un tipo específico de proveedor. Por ejemplo, para limitar la cantidad de tiempo que un proveedor de propiedades puede permanecer inactivo, editaría la propiedad ClearAfter de una instancia de __PropertyProviderCacheControl en el espacio de nombres \root.
Descargar un proveedor que también es un cliente WMI
Es posible que el proveedor deba permanecer como cliente de WMI después de haber completado las funciones del proveedor a las que se llamó para realizar. Por ejemplo, un proveedor de inserción puede necesitar emitir consultas a WMI. Para obtener más información, vea Determinar el estado de inserción o extracción. En este caso, la propiedad Pure de la instancia de __Win32Provider que representa el proveedor debe establecerse en TRUE. Si la propiedad Pure se establece en FALSE, el proveedor se prepara para descargar llamando a IUnknown::Release en todos los puntos de interfaz pendientes cuando WMI llama al método Release de su interfaz principal. Para obtener más información, vea la sección Comentarios de __Win32Provider.
En el procedimiento siguiente se describe cómo implementar un método de versión para la interfaz principal del proveedor.
Para descargar un proveedor
Libere todos los punteros de interfaz mantenidos en WMI cuando WMI llama al método Release de la interfaz principal del proveedor.
Normalmente, un proveedor contiene punteros a las interfaces IWbemServices e IWbemContext proporcionadas en IWbemProviderInit::Initialize.
Si la propiedad Pure de la instancia de __Win32Provider asociada se establece en FALSE, el proveedor puede realizar la transición al rol de la aplicación cliente después de llamar a Release de WMI. Sin embargo, WMI no puede descargar un proveedor que funciona como sistema cliente, lo que aumenta la sobrecarga del sistema.
Un proveedor con Pure establecido en TRUE solo existe en las solicitudes de servicio. Por lo tanto, este tipo de proveedor no puede asumir el rol de una aplicación cliente y WMI puede descargarlo.
Descargar un proveedor durante el apagado
En circunstancias normales, el uso de las directrices de Descarga de un proveedor que también es un cliente WMI permite a WMI descargar el proveedor correctamente. Sin embargo, puede encontrarse en situaciones en las que WMI no puede instigar los procedimientos de descarga normales, como cuando el usuario decide apagar el sistema. Mediante el uso de un modelo de transacción de almacenamiento de datos, además de implementar una buena estrategia de limpieza, puede asegurarse de que el proveedor se descarga correctamente.
El usuario puede detener WMI en cualquier momento. En tal situación, WMI no descarga ningún proveedor ni llama al punto de entrada DllCanUnloadNow en ningún proveedor en proceso. Además, si un proveedor en proceso está en medio de una llamada de método en el momento del apagado, WMI puede terminar el subproceso en ejecución en medio de la llamada. En esta circunstancia, WMI no llama a rutinas que normalmente controlan la limpieza, como un destructor de objetos. Como máximo, WMI llamará solo a DllMain .
Cuando el sistema operativo apaga WMI, el sistema libera automáticamente toda la memoria asignada a un proveedor en proceso. El sistema operativo también cierra la mayoría de los recursos mantenidos por el proveedor, como identificadores de archivo, identificadores de ventana, etc. El proveedor no necesita realizar ninguna acción específica para que esto suceda.
Dado que WMI puede apagarse en medio de una llamada, un proveedor no debe dejar orígenes de datos en un estado incoherente. Dejar los datos en un estado incoherente no es un problema para los proveedores de solo lectura. Sin embargo, es posible que los proveedores con funcionalidades de escritura quieran implementar algún tipo de modelo de transacción para permitir una reversión segura después de una terminación abrupta.
Aunque el sistema operativo puede liberar algunos recursos generales del sistema, el sistema no libera automáticamente todos los recursos. Por ejemplo, es posible que el sistema operativo no libere un socket o una conexión de base de datos. En su lugar, es posible que el proveedor tenga que limpiar manualmente estos recursos. Para evitar estos problemas, puede implementar el proveedor fuera de proceso o agregar código de limpieza.
La solución más sencilla es implementar el proveedor fuera de proceso. Un proveedor fuera de proceso no se elimina cuando WMI se cierra, aunque WMI liberará el proveedor después de un tiempo de espera COM. Los proveedores para los que los problemas de solidez de limpieza y finalización son más importantes que el rendimiento puede estar fuera del proceso.
Si debe colocar código de limpieza en el proveedor, tiene dos opciones. Un lugar para realizar este tipo de limpieza es DllMain, la función de punto de entrada dll que el sistema operativo llama al descargar el archivo DLL. El código de limpieza se puede agregar directamente a DllMain, ejecutándolo en respuesta a DLL_PROCESS_DETACH. La implementación de código de limpieza en DllMain puede ser algo difícil de organizar, especialmente en entornos de programación como MFC o ATL. Para obtener más información, vea el artículo Q148791 de Microsoft Knowledge Base, "How to Provide Your Own DllMain in an MFC Regular DLL". (Es posible que este recurso no esté disponible en algunos idiomas y países o regiones).
Como alternativa, también puede colocar el código de limpieza en el destructor de una clase global. Para obtener más información, consulte Descarga de un proveedor. El sistema operativo Windows no asigna objetos globales en el montón. En su lugar, el sistema operativo llama a los destructores durante la descarga de DLL.
A continuación se muestra un procedimiento de limpieza sencillo que podría caber dentro de un objeto global para WMI.
class CMyCleanup
{
~CMyCleanup()
{
CloseHandle(m_hOpenFile);
CloseDatabaseConnection(g_hDatabase);
}
} g_Cleanup;
Hay muchas restricciones en cuanto a lo que se puede hacer en el código de limpieza con cualquier enfoque. Por ejemplo, ni los subprocesos ni los archivos DLL que no estén vinculados implícitamente se pueden acceder de ninguna manera. Además, no puede realizar llamadas COM en ninguna circunstancia.
Temas relacionados