|
JavaScript, Visual Basic, WMI |
|
Fundamentos |
WMI (Windows
Management Instrumentation) |
|
Septiembre/2000 |
|
|
Marino Posadas es MVP en .NET Framework, Microsoft Certified Solution Developer (MCSD), MCAD (Microsoft Certified Application Developer en .NET), MCT(Microsoft Certified Trainer) y autor de numerosos artículos para revistas especializadas, así como de varias obras editadas por Editorial Ra-Ma en solitario y junto a Grupo EIDOS. Trabaja como Consultor para Grupo EIDOS. |
|
|
|
La aparición de Windows 2000 no sólo ha supuesto un cambio importante en las posibilidades de administración del sistema operativo, sino también un reto para el programador en nuevas tecnologías, gracias a un conjunto de servicios que, en parte extienden (COM+) y en parte introducen avances sobre lo disponible bajo Win98/NT.
Una de esas novedades es WMI (Windows Management Instrumentation), el nombre que Microsoft ha dado a su implementación de un estándar para la gestión integrada de sistemas llamado Web Based Enterprise Management (gestión basada en la web). Dicha información incluye información sobre el estado de la memoria del sistema, inventarios de todas las aplicaciones instaladas en un equipo o en un dominio, y mucha otra información de cliente adicional.
Se ha implementado para todas las plataformas de Windows (incluyendo Windows 95), y permite que sistemas, aplicaciones, redes y componentes sean representados utilizando un modelo de objetos programable llamado CIM (Common Information Model o Modelo común de información), otro estándar publicado por la DMTF (Distributed Management Task Force).
Además de la modelización de datos, WMI ofrece un potente conjunto de servicios de base que incluyen consultas sobre información genérica del sistema y aplicaciones y suscripción a eventos (la capacidad que tiene el sistema de avisar al usuario cuando se produzca una circunstancia predefinida por él). La programación de estos servicios se basa en COM y el paquete de desarrollo de WMI incluye herramientas para crear aplicaciones cliente y proveedores WMI.
Requisitos del sistema
Para instalar el paquete de desarrollo (WMI SDK), es necesario tener instalado Windows 2000 ó Windows NT 4.0 SP5, además de Internet Explorer 5.0 (por la máquina virtual de Java). Debe de instalarse con permiso de administrador bajo estas plataformas.
Para la instalación de los servicios cliente, puede usarse Windows 2000, Windows NT 4 SP4, Windows 98 o Windows 95 SR2. En cuanto a hardware, se precisa un Pentium con 32MB de RAM, 30MB de espacio en disco, tarjeta gráfica de 256 colores (resolución de 800/600) y tarjeta de red. Finalmente, respecto al compilador, WMI está pensado para usar Visual Studio 6.0.
Infraestructura de WMI
WMI consiste, fundamentalmente, de dos elementos:
EL software WMI (Winmgmt.exe) un componente que provee un acceso homogéneo a las aplicaciones para la gestión de datos.
El repositorio de objetos CIM, una central de almacenamiento de objetos programables, que reflejan todo el sistema.
Pero la utilización de WMI, supone la presencia de un programa (aplicación gestora), que haga uso de los servicios proporcionados por WMI. Para obtener la información, la aplicación realizará peticiones mediante métodos de las COM API o bien de las Scripting API, dos interfaces de programación que exponen al desarrollador un conjunto de métodos de acceso a los servicios de WMI.
Mediante estas API, el programador tiene acceso a un variado conjunto de servicios, tales como inventarios de red, información de configuración y utilización del sistema, respuesta a evento o la puesta en marcha o detención de servicios del sistema. Para conseguirlo, WMI soporta varias estrategias para la implementación de aplicaciones de gestión de sistema:
Desde los navegadores, se pueden usar un conjunto de controles ActiveX, para controlar la apariencia, relaciones y comportamiento de los datos relativos a los objetos manejados por la aplicación. También pueden utilizar ISAPI (Internet Server API) para acceder a dichos servicios a través de HTML Dinámico.
Las aplicaciones de bases de datos pueden utilizar el Adaptador ODBC WMI, para fusionar las capacidades de gestión de datos ODBC con las propias de WMI.
Las aplicaciones que hagan uso del Servicio de Directorio Activo pueden utilizar WMI Active Directory Service Interface (ADSI), para integrar los servicios de directorio con los datos.
Mientras el COM API está disponible directamente a los programadores de C++, Scripting API puede ser usado por programadores que conozcan Visual Basic (estándar o script) para controlar o visualizar los objetos del CIM. Concretamente, WMI suministra soporte para los siguientes lenguajes:
Visual Basic
Visual Basic para Aplicaciones
Visual Basic Scripting
Microsoft® JScript®
El gráfico adjunto (tomado del WMI SDK) ilustra estos posibles escenarios de trabajo:

Proveedores WMI
Los proveedores WMI actúan como intermediarios entre WMI y los objetos manejados. Cuando WMI recibe una petición de una aplicación acerca de información que no está disponible en el repositorio CIM o en el caso de necesitarse una notificación sobre un evento que no soporta CIM directamente, se emite esa petición al proveedor. Cada proveedor suministra información específica de su dominio. Desde el punto de vista de la programación, dichos servidores son componentes DCOM (ActiveX DLL, servicios de NT/2000 locales o remotos o ejecutables estándar). También es posible crear proveedores específicos de usuario para aplicaciones de terceras partes.
CIM
La labor de CIM es presentar al programador un modelo consistente y uniforme de todos los tipos de objetos físicos y lógicos de un sistema. Los objetos se representan mediante clases que contienen propiedades y métodos para describir sus características y comportamiento.
En CIM se definen 3 niveles de clases:
Clases que representan objetos pertenecientes a todas las áreas administrativas de un sistema.
Clases que representan objetos de áreas específicas, pero independientes de una implementación o tecnología concretas.
Clases que representan objetos dependientes de una tecnología dada (por ejemplo, específicas de UNIX o de Win32).
Pueden existir clases derivadas, que heredan de sus ancestros tanto métodos como propiedades.
El programa WinMgmt.exe
Winmgt.exe es el componente principal de la infraestructura de gestión de WMI. Bajo Windows 98, funciona como un ejecutable independiente. Bajo Windows NT/2000, como un servicio. Cuando una aplicación de gestión WMI solicita un dato, el programa determina si éste se encuentra en el repositorio CIM o es necesario obtenerlo a partir de un proveedor. Como norma general, los datos estáticos suelen encontrarse siempre en el repositorio CIM, mientras que los dinámicos requieren el concurso de un proveedor.
Además de estas labores, WMI suministra los siguientes servicios adicionales:
Soporte de notificación de eventos
Lenguaje de consultas
Soporte de seguridad
Almacenamiento de funciones de múltiples lenguajes en el CIM
WMI en la práctica
La explicación completa de este sistema de gestión de entornos de trabajo está fuera del ámbito de ésta introducción, si bien puede encontrarla el lector en el SDK de WMI accesible desde la dirección de Internet http://msdn.microsoft.com/downloads/sdks/wmi/tutorial.asp.
No obstante, para completar esta visión inicial del producto, vamos a poner algunos ejemplos de funcionamiento, que ayudarán a comprender sus posibilidades.
Llamadas a valores del sistema
Con WMI podemos obtener mediante programación valores del sistema operativo y datos de configuración. Para ello, debemos usar los objetos definidos a tal efecto y llamarlos utilizando una de las dos interfaces de programación de aplicaciones que hemos comentado anteriormente: El API COM (a través de C/C++) o bien el Script API, para las llamadas desde entornos de más alto nivel, como Visual Basic, o una página Web.
1) Llamadas desde una página Web usando Javascript
Muchos de los métodos de Scripting WMI se encuentran disponibles como métodos síncronos o asíncronos. Cuando usamos Javascript para llamar a un servicio y obtener un valor, debemos tener instalados algunos componentes que nos permitan establecer esas conexiones, y más tarde invocar sus métodos y propiedades.
En el ejemplo, se utiliza una página web muy simple, en la que se hace referencia a un objeto que nos proporciona el acceso a los datos del CIM, llamado WbemScripting.SWbemLocator.
La salida en el explorador es la siguiente:

Información del servicio mostrada por la página de prueba en Internet Explorer 5
Una vez que se muestra la ventana, ya existe una instancia del objeto WbemScripting.SWbemLocator, con el nombre Buscador. Al pulsar sobre la página, se invoca el método ConnectServer, para obtener una referencia a los servicios de CIM. A continuación se llama al método Get de ese objeto, para obtener una referencia al servicio de Win32 llamando Winmgmt (el propio servicio de CIM). Finalmente, se muestra el valor correspondiente al nombre del servicio (DisplayName) en un objeto SPAN de HTML. La secuencia completa de código es la siguiente:
|
Código de la llamada al nombre de un servicio mediante Javascript |
|---|
| <!- Copyright (c) 1997-1999 Microsoft Corporation-> <!- Modificado y traducido por Marino Posadas (Grupo EIDOS) -> <HTML> <!--------------------------------------------------------------- Ejemplo de uso de WMI Scripting API en una página HTML, usando JavaScript. Muestra el nombre de Win32_service usando un API síncrono. Se instancia el objeto WMI mediante su CLSID ------------------------------------------------------------------> <head> <title>WMI Scripting HTML (JavaScript síncrono)</title> <script FOR="document" EVENT="onclick()" LANGUAGE="JScript"> var servicio = Buscador.ConnectServer(); var proceso = servicio.Get('Win32_Service.Name="Winmgmt"'); document.all.DatosServicio.innerText = proceso.DisplayName; </script> </head> <body> <P>Pulse sobre la ventana para obtener el nombre del servicio: <SPAN style="color:red" ID="DatosServicio">Desconocido</SPAN>. <object ID="Buscador" CLASSID="CLSID:76A64158-CB41-11D1-8B02-00600806D9B6"> </object> </P> </body> </HTML> |
De la misma forma, podríamos haber usado VBScript, instanciando el objeto Buscador a través de su nombre registrado (WbemScripting.SWbemLocator), según el código adjunto:
|
Código de la llamada al nombre de un servicio mediante VBScript |
|---|
| <!- Copyright (c) 1997-1999 Microsoft Corporation-> <!- Modificado y traducido por Marino Posadas (Grupo EIDOS) -> <HTML> <!--------------------------------------------------------------- Ejemplo de uso de WMI Scripting API en una página HTML, usando VBScript. Muestra el nombre de Win32_service usando un API síncrono. Se instancia el objeto WMI mediante su nombre registrado. ------------------------------------------------------------------> <head> <title>WMI Scripting HTML (VBScript síncrono)</title> <script LANGUAGE="JScript"> Sub window_onload() Set Buscador =
CreateObject("WbemScripting.SWbemLocator") End Sub |
Como vemos, los dos ejemplos son muy similares, con la salvedad del lenguaje de script utilizado y la forma de instanciar el objeto.
La otra forma de trabajo que mencionábamos, es a través de un lenguaje de programación como Visual Basic. Vamos a ver un ejemplo del SDK de Microsoft, adaptado y traducido para este artículo. Se trata de un formulario que permite visualizar el estado de todos los servicios de Windows 2000/NT y permite detenerlos, reanudarlos, e iniciarlos.
El ejemplo utiliza un formulario básico de Visual Basic con unos botones de control y un ListView para mostrar la lista de servicios. Para conseguir el manejo de los objetos que representan los servicios, usa instancias de las clases predefinidas de WMI SWbemLocator (para los accesos, como en el programa anterior) y SWbemServices, para los servicios del sistema. Así mismo, para controlar el momento en que un servicio ha cambiado su estado (Iniciado, Detenido, etc.), utiliza una instancia del objeto SWbemSink, para capturar el evento OnObjectReady, que tiene lugar cada vez que un objeto WMI cambia su estado.
Una vez que el programa se pone en funcionamiento, obtenemos una lista de servicios en el ListView como se aprecia en la figura adjunta:

Vista de los Servicios de Windows 2000 mediante el ejemplo
Y el código fuente correspondiente a dicha salida es el siguiente:
|
Título explicativo o nombre del fichero asociado al código fuente |
|---|
| ' Copyright
(c) 1997-1999 Microsoft Corporation ' Revisión y Adaptación: Marino Posadas (Grupo EIDOS) '------------------------------------------------------------------------- ' ' Este ejemplo ilustra el uso del API WMI Scripting con VB. ' Muestra información de los servicios de un host local o remoto ' y permite un control básico (parar, iniciar, reanudar...) ' '---------------------------------------------------------------------------- Public Buscador As SWbemLocator Public Servicios As SWbemServices Public Cronometro Public Item As ListItem Dim WithEvents Depósito As SWbemSink ----------------------------------------------------------------------------- Public Sub InitialiseView() ListView1.ListItems.Clear End Sub ----------------------------------------------------------------------------- Private Sub Reloj_Timer() Cronometro = Cronometro + 1 If Cronometro > 10 Then Item.Bold = False Reloj.Enabled = False Cronometro = 0 Else Item.Bold = Not Item.Bold End If End Sub ----------------------------------------------------------------------------- Private Sub Depósito_OnObjectReady(ByVal Object As WbemScripting.ISWbemObject, ByVal AsyncContext As WbemScripting.ISWbemNamedValueSet) Dim NombreServicio Dim Serviciostatus NombreServicio = Object.TargetInstance.Name Serviciostatus = Object.TargetInstance.State Set Item = ListView1.FindItem(NombreServicio) Item.SubItems(2) = Serviciostatus Item.Bold = True Reloj.Enabled = True Cronometro = 0 End Sub ----------------------------------------------------------------------------- Public Sub LoadView() Dim Enumerator As SWbemObjectSet Dim Object As SWbemObject Dim Item As ListItem On Error Resume Next SavePointer = Form1.MousePointer Form1.MousePointer = vbHourglass Form1.Enabled = False ListView1.ListItems.Clear Depósito.Cancel Set Servicios = Buscador.ConnectServer(Server.Text) Servicios.ExecNotificationQueryAsync Depósito, "Select * from __InstanceModificationEvent Within 2.0 Where TargetInstance Isa 'Win32_Service'" Set Enumerator = Servicios.ExecQuery("Select * From Win32_Service") For Each Object In Enumerator Set Item = ListView1.ListItems.Add(, Object.Name, Object.Name) Item.SubItems(1) = Object.Description Item.SubItems(2) = Object.State Next Form1.Enabled = True Form1.MousePointer = SavePointer End Sub ----------------------------------------------------------------------------- Private Sub Form_Load() Set Buscador = New SWbemLocator Set Depósito = New SWbemSink InitialiseView LoadView End Sub ----------------------------------------------------------------------------- Private Sub cmdConectar_Click() LoadView End Sub ----------------------------------------------------------------------------- Private Sub cmdPausar_Click() Dim ObjetoServicio As SWbemObject Dim NombreServicio On Error Resume Next NombreServicio = ListView1.SelectedItem.Text If Err.Number = 0 Then Set ObjetoServicio = Servicios.Get("Win32_Service='" & NombreServicio & "'") 'Obsérvese como el método "PauseService" de Win32_Service 'se ejecuta como si fuera método de automatización de SWbemObject ObjetoServicio.PauseService End If End Sub ----------------------------------------------------------------------------- Private Sub cmdIniciar_Click() Dim ObjetoServicio As SWbemObject Dim NombreServicio On Error Resume Next NombreServicio = ListView1.SelectedItem.Text If Err.Number = 0 Then ' Obsérvese cómo el método CIM "StartService" de Win32_Service ' se ejecuta como si fuera un método de automatización de SWbemObject Set ObjetoServicio = Servicios.Get("Win32_Service='" & NombreServicio & "'") ObjetoServicio.StartService End If End Sub ----------------------------------------------------------------------------- Private Sub cmdParar_Click() Dim ObjetoServicio As SWbemObject Dim NombreServicio On Error Resume Next NombreServicio = ListView1.SelectedItem.Text If Err.Number = 0 Then Set ObjetoServicio = Servicios.Get("Win32_Service='" & NombreServicio & "'") ObjetoServicio.StopService End If End Sub |
Esto sólo han sido un par de ejemplos de las posibilidades de WMI para los programadores y para los administradores de sistemas. El horizonte es mucho más amplio que lo mencionado aquí, tanto en el apartado teórico como en el práctico. Recomendamos a los lectores interesados la descarga del SDK completo (unos 8 MB) disponible en la dirección de Internet citada más arriba.