Usar WMI/CIM desde C# y PowerShell ── Guía práctica de obtención de información de hardware, monitorización de procesos y consultas remotas

· Actualizado el: · · Windows, C#, .NET, PowerShell, WMI, CIM, Aplicaciones empresariales, Desarrollo en Windows

«Quiero mostrar el número de serie y el modelo del PC en la pantalla de la aplicación empresarial», «quiero monitorizar el espacio libre en disco del servidor y avisar cuando escasee», «quiero detectar que se ha iniciado un proceso concreto», «quiero consultar de forma centralizada el estado de PC ubicados en otro lugar» ── en el desarrollo de aplicaciones empresariales y herramientas de administración para Windows, este tipo de solicitudes son habituales. Y la respuesta habitual a ellas es WMI (Windows Management Instrumentation), o, dicho con su nombre estándar, CIM (Common Information Model).

Solicitudes habituales y WMI/CIMLa respuesta habitual a las solicitudes típicas de las aplicaciones empresariales, mostrar el número de serie y el modelo, monitorizar el espacio libre en disco, detectar el inicio de procesos y consultar PC remotos, es WMI, cuyo nombre estándar es CIMNúmero de serie y modeloWMI(cuyo nombre estándar es CIM)Monitorizar el espacio libre en discoDetectar el inicio de procesosConsultar PC remotos

Figura 1: WMI/CIM es la respuesta habitual a las cuatro solicitudes típicas de las aplicaciones empresariales.

Lo complicado es que la información sobre WMI mezcla lo antiguo y lo nuevo. Al buscar, conviven artículos de hace diez años que usan Get-WmiObject con artículos que usan Get-CimInstance, y en el lado de C# también hay dos líneas: System.Management y Microsoft.Management.Infrastructure. Es difícil distinguir cuál es la forma actual de escribirlo y cuál es «todavía funciona, pero no se elige para código nuevo». De hecho, Get-WmiObject no existe en PowerShell 7, y el problema suele aflorar de repente al migrar scripts internos escritos para 5.1.

Este artículo está dirigido a desarrolladores de C#/PowerShell que implementan la obtención de información de hardware, la monitorización de procesos y la consulta de PC remotos en aplicaciones empresariales. Organiza, con base en fuentes primarias vigentes en agosto de 2026, desde la comprensión mínima de la estructura de WMI/CIM hasta los cmdlets CIM de PowerShell, las dos API de C#, recetas prácticas de uso habitual, las trampas de rendimiento, permisos y 64 bits, y el criterio para decidir «cuándo no conviene usar WMI».

1. Conclusión principal

  • CIM es el estándar de la industria para la información de administración definido por el DMTF, y WMI es su implementación de Microsoft. Las API de la familia «CIM» de PowerShell y C# son las API de la generación actual que siguen ese estándar, y se conectan a la misma infraestructura de WMI. 1
  • En PowerShell, lo actual son los cmdlets CIM (Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent). Los antiguos cmdlets WMI (los cinco, entre ellos Get-WmiObject) se eliminaron a partir de PowerShell 6 y no funcionan en PowerShell 7. 2
  • El espacio de nombres predeterminado es root/CIMV2, y la forma básica de las consultas diarias es filtrar con WQL las clases Win32_* que hay ahí. 3
  • WSMan (WinRM) es el predeterminado para las consultas remotas. Al indicar -ComputerName se crea una sesión temporal WSMan. Si se va a consultar varias veces al mismo destino, lo habitual por rendimiento es reutilizar una sesión CIM (New-CimSession), y para destinos antiguos donde no se puede configurar WinRM existe la opción del protocolo DCOM. 34
  • En C# hay dos líneas: System.Management (ManagementObjectSearcher) y Microsoft.Management.Infrastructure (CimSession). Ambas son exclusivas de Windows y, en el .NET actual, se instalan desde NuGet. Si se va a hacer en serio la parte remota o de monitorización, la API MI, que comparte el sistema de tipos con los cmdlets CIM, es la más adecuada. 56
  • Detecte el inicio de procesos mediante suscripción a eventos, no con sondeo (polling). La suscripción a Win32_ProcessStartTrace debe ejecutarse con privilegios de administrador. 78
  • No use SELECT * por comodidad. Filtrar los datos a transferir con -Filter / -Property / -KeyOnly previene la mitad de los problemas de rendimiento de WMI. 3
  • WMI no es una solución universal. Para la monitorización de rendimiento de alta frecuencia, la lectura y escritura de la configuración de la propia aplicación o las llamadas puntuales a funciones del sistema operativo, son más adecuados los contadores de rendimiento, el registro, la API de Win32 o los cmdlets dedicados (tabla de decisión del capítulo 8).

2. Qué es WMI/CIM ── Estándar e implementación, espacios de nombres, clases y WQL

Primero, aclaremos de una vez la relación entre los términos.

Término Qué es
CIM (Common Information Model) Modelo estándar de la industria para representar objetos administrados, como sistemas, aplicaciones, redes y dispositivos. Definido y mantenido por el DMTF (Distributed Management Task Force)1
WBEM (Web-Based Enterprise Management) Iniciativa de la industria que crea la tecnología estándar para acceder a la información de administración en entornos empresariales1
WMI Implementación de Microsoft de WBEM. Representa los objetos administrados usando el estándar CIM y viene integrado en Windows1
MI (Windows Management Infrastructure) Versión de próxima generación de WMI. Totalmente compatible con el WMI tradicional; la mayoría de los proveedores nuevos están escritos en MI1
Relación entre el estándar CIM y la implementación WMIEl estándar CIM, definido y mantenido por el DMTF, se usa dentro del marco de la iniciativa WBEM, su implementación de Microsoft es WMI, la versión de próxima generación MI es totalmente compatible con el WMI tradicional, y las API de la familia CIM se conectan a la misma infraestructura de WMIDefinido y mantenido por el DMTFCIM(modelo estándar de la industria)WBEM(iniciativa de la industria)WMI(implementación de Microsoft)MI(próxima generación, totalmente compatible)API de la familia CIM(PowerShell / C#)

Figura 2: CIM es la especificación, WMI es su implementación en Windows. Las API de la familia CIM se conectan a la misma infraestructura de WMI.

Como desarrollador, hay cuatro elementos de la estructura que conviene tener claros.

  • Espacio de nombres (namespace): es la jerarquía que agrupa las clases. En las consultas diarias se usa casi siempre root/CIMV2, que también es el predeterminado de los cmdlets CIM. 3 También existen otros, como root\default (por ejemplo, el proveedor del registro).
  • Clase: es el tipo del objeto administrado, como Win32_ComputerSystem (el equipo en sí), Win32_LogicalDisk (una unidad lógica) o Win32_Process (un proceso). Las clases específicas de Windows que heredan de una clase del estándar CIM (como CIM_LogicalDisk) llevan el prefijo Win32_. 9
  • Proveedor: es el componente que aporta la entidad real de la clase. Al consultar, el proveedor pregunta al sistema operativo en el momento y genera los valores.
  • WQL: es un lenguaje de consulta similar a SQL. Trata la clase como si fuera una tabla y filtra, por ejemplo, con SELECT Name, State FROM Win32_Service WHERE StartMode = 'Auto'. El lenguaje de consulta predeterminado de los cmdlets CIM también es WQL. 3
Estructura de una consulta WMILa consulta WQL se dirige a las clases Win32_* dentro del espacio de nombres root/CIMV2, el proveedor que ofrece la entidad de la clase consulta al sistema operativo en el momento para generar los valores, y se devuelve el resultadoConsulta con WQLEspacio de nombres root/CIMV2Clase Win32_*ProveedorConsulta al SO en el momentoDevuelve el resultado

Figura 3: La consulta recorre el espacio de nombres, la clase y el proveedor en ese orden, y los valores se generan en el momento.

«Poder leer la información del sistema operativo y del hardware con un conjunto unificado de clases y un lenguaje de consulta» ── ese es el valor de WMI. Dicho de otro modo, la escritura o la manipulación se limita a las clases que tienen métodos invocables con Invoke-CimMethod; no es un mecanismo capaz de hacerlo todo.

3. Uso desde PowerShell ── Los cmdlets CIM son los actuales; los cmdlets WMI ya se eliminaron

3.1. Lo básico: Get-CimInstance

# Especificar la clase (espacio de nombres predeterminado root/CIMV2)
Get-CimInstance -ClassName Win32_OperatingSystem

# Escribir solo la cláusula WHERE en -Filter (sin la palabra clave WHERE)
Get-CimInstance -ClassName Win32_Service -Filter "StartMode = 'Auto' AND State <> 'Running'"

# Obtener solo las propiedades necesarias para reducir el volumen transferido
Get-CimInstance -ClassName Win32_Process -Property Name, ProcessId, CreationDate

# Si se quiere escribir WQL directamente, usar -Query
Get-CimInstance -Query "SELECT * FROM Win32_Process WHERE Name LIKE 'p%'"

-Filter es directamente la cláusula WHERE de WQL, y -Property limita las columnas obtenidas. 3 El valor devuelto es un objeto CimInstance, y las propiedades de fecha (como CreationDate o LastBootUpTime) se devuelven ya convertidas a DateTime. A diferencia del antiguo Get-WmiObject, el objeto obtenido no tiene métodos propios, así que la llamada a un método se hace pasándolo a Invoke-CimMethod.

Llamada a métodos de CimInstanceEl CimInstance que devuelve Get-CimInstance trae las propiedades de fecha ya convertidas a DateTime pero no tiene métodos propios, por lo que la llamada a un método se hace pasando la instancia a Invoke-CimMethodGet-CimInstanceObjeto CimInstanceLas fechas ya están convertidas a DateTimeNo tiene métodos propiosSe pasa a Invoke-CimMethodLlamada al método

Figura 4: Como CimInstance no tiene métodos, la llamada a un método se hace pasándolo a Invoke-CimMethod.

# Llamar a un método de instancia: obtener el propietario de cada proceso
Get-CimInstance -ClassName Win32_Process -Filter "Name = 'notepad.exe'" |
    Invoke-CimMethod -MethodName GetOwner

# Llamar a un método estático de la clase: iniciar un proceso
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = 'notepad.exe' }

# Consultar la definición de la clase (lista de propiedades y métodos)
Get-CimClass -ClassName Win32_Process

3.2. Tabla de migración desde los antiguos cmdlets WMI

A partir de PowerShell 6 (la versión actual, PowerShell 7), los siguientes cmdlets WMI v1 han sido eliminados. La misma funcionalidad la ofrece el módulo CimCmdlets (WMI v2). 2

Antiguo (hasta Windows PowerShell 5.1) Actual (cmdlets CIM) Nota
Get-WmiObject Get-CimInstance El concepto de -Filter / -Query es el mismo
Get-WmiObject -List Get-CimClass Exploración de clases y comprobación de su definición
Invoke-WmiMethod Invoke-CimMethod Los argumentos se pasan como tabla hash en -Arguments @{ }
Register-WmiEvent Register-CimIndicationEvent Suscripción a eventos (apartado 6.3)
Set-WmiInstance Set-CimInstance Cambio de propiedades editables
Remove-WmiObject Remove-CimInstance Eliminación de instancias

Como los cmdlets CIM también funcionan en Windows PowerShell 5.1, lo que se escriba de nuevo conviene escribirlo con CIM aunque vaya a ejecutarse en 5.1; así no queda coste de migración pendiente. El panorama general de la convivencia y la migración entre 5.1 y 7 está recogido en «Diferencias entre Windows PowerShell 5.1 y PowerShell 7».

Por qué escribir los scripts nuevos con CIMUn script escrito con cmdlets WMI funciona en 5.1 pero como fueron eliminados a partir de PowerShell 6 hay que reescribirlo al migrar, en cambio los cmdlets CIM también funcionan en 5.1 así que si lo nuevo se escribe con CIM no queda coste de migración pendienteCmdlets WMICmdlets CIMScript nuevo¿Con cuál escribirlo?Funciona en 5.1También funciona en 5.1Eliminados en PowerShell 7Reescritura al migrarSin coste de migración pendiente

Figura 5: Escribiendo lo nuevo con cmdlets CIM, no hace falta reescribirlo al migrar a PowerShell 7.

4. Consultas remotas ── Sesiones CIM (WSMan por defecto) y la opción DCOM

Los cmdlets CIM, si no se indica nada, se conectan por COM al WMI local; si se indica -ComputerName, se conectan creando una sesión temporal con el protocolo WSMan (WinRM). Cuando se van a realizar varias operaciones sobre el mismo equipo, es más ventajoso por rendimiento crear una sesión CIM y reutilizarla. 3

Elección del método de conexión CIMSin especificar nada se conecta por COM al WMI local, al indicar ComputerName se crea una sesión temporal WSMan en cada consulta, para varias operaciones contra el mismo destino reutilizar una sesión con New-CimSession es más eficiente, y para destinos sin WinRM configurado existe la opción del protocolo DCOMNoUna sola vezVariasEjecución del cmdlet CIM¿Se indica ComputerName?Conexión COM al WMI local¿Varias operaciones contra el mismo destino?Sesión temporal WSManReutilizar New-CimSessionSe crea en cada consultaDestino sin WinRM configuradoOpción de protocolo DCOM

Figura 6: WSMan es el predeterminado para las consultas remotas; para varias operaciones contra el mismo destino, lo habitual es reutilizar la sesión CIM.

# Para un uso puntual, -ComputerName (se crea una sesión temporal en cada llamada)
Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName Server01, Server02

# Para consultas repetidas, reutilizar una sesión CIM
$session = New-CimSession -ComputerName Server01
Get-CimInstance -ClassName Win32_OperatingSystem -CimSession $session
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" -CimSession $session
Remove-CimSession $session

Para destinos con los que no se puede conectar por WSMan, como máquinas antiguas donde no se puede configurar WinRM, se puede elegir el protocolo DCOM. 4

$dcom = New-CimSessionOption -Protocol Dcom
$session = New-CimSession -ComputerName OldServer -SessionOption $dcom

Los requisitos previos para las consultas remotas son los siguientes.

  • Que WinRM esté configurado en el destino. winrm quickconfig realiza de una vez el arranque automático del servicio, la creación del agente de escucha HTTP (puerto predeterminado 5985) y el registro de la excepción del firewall. 10 Si se quiere conectar por HTTPS (puerto predeterminado 5986), esto no basta: hay que preparar un certificado de servidor y configurar aparte el agente de escucha HTTPS, por ejemplo con winrm quickconfig -transport:https. 10
  • Que el puerto correspondiente esté abierto en el firewall del trayecto. El diseño y el registro práctico de las reglas de entrada se tratan en el artículo «El firewall de Windows y las aplicaciones empresariales».
  • Autenticación. En un entorno de dominio, la autenticación mutua se realiza con Kerberos. En un grupo de trabajo no se puede usar Kerberos, por lo que puede ser necesario registrar el destino en TrustedHosts del lado cliente. Limite ese registro al mínimo imprescindible. 10
  • Permisos. Con la configuración predeterminada, la consulta u operación remota de WMI se realiza básicamente con una cuenta que pertenece al grupo de administradores del destino. Si se quiere abrir a usuarios estándar, hay que configurar los permisos de acceso tanto en WinRM como en el espacio de nombres de WMI. 10
  • Cabe señalar que DCOM no tiene un puerto de escucha fijo (usa puertos dinámicos de RPC), lo que dificulta el diseño cuando hay que atravesar un firewall. Para los mecanismos que se construyan de aquí en adelante, lo prudente es considerar WSMan como opción predeterminada.
Comprobación de los requisitos de las consultas remotasEn el destino winrm quickconfig realiza de una vez el arranque automático del servicio, la creación del agente de escucha HTTP y el registro de la excepción del firewall, el agente de escucha HTTPS se configura aparte con un certificado, y en un entorno de grupo de trabajo puede ser necesario registrar el destino en TrustedHostswinrm quickconfigArranque automático del servicioCreación del agente de escucha HTTP(5985)Excepción del firewallAgente de escucha HTTPS(5986)Se prepara el certificado y se configura aparteEntorno de grupo de trabajoRegistro en TrustedHosts

Figura 7: winrm quickconfig realiza de una vez la configuración predeterminada; el agente de escucha HTTPS y la autenticación en grupo de trabajo se atienden aparte.

5. Uso desde C# ── System.Management y Microsoft.Management.Infrastructure

Hay dos líneas de API para usar WMI desde C#. Ambas son exclusivas de Windows.

  System.Management Microsoft.Management.Infrastructure (API MI)
Instalación Estándar en .NET Framework. En el .NET actual, paquete NuGet System.Management5 Paquete NuGet Microsoft.Management.Infrastructure6
Clase de entrada ManagementObjectSearcher (se consulta pasando WQL)5 CimSession (Create → QueryInstances / InvokeMethod / Subscribe)6
Sistema de tipos ManagementObject / ManagementEventWatcher11 CimInstance / CimSession ── el mismo tipo que los cmdlets CIM3
Remoto Basado en DCOM Basado en WSMan (sesión CIM). Hay versión asíncrona (*Async)6
Casos adecuados Obtención de información local. Mantenimiento de código existente Incorporar consultas remotas y monitorización. Diseño combinado con PowerShell

5.1. System.Management: lo básico de ManagementObjectSearcher

Se pasa WQL como cadena y se recibe la colección de resultados con Get(). 5

// NuGet: System.Management (exclusivo de Windows)
using System.Management;

using var searcher = new ManagementObjectSearcher(
    @"root\cimv2",
    "SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");

foreach (ManagementObject disk in searcher.Get())
{
    var freeGb = (ulong)disk["FreeSpace"] / 1024.0 / 1024.0 / 1024.0;
    var sizeGb = (ulong)disk["Size"] / 1024.0 / 1024.0 / 1024.0;
    Console.WriteLine($"{disk["DeviceID"]} libre {freeGb:F1} GB / total {sizeGb:F1} GB");
}

Como las propiedades se devuelven como object a través del indexador, hay que consultar el tipo CIM en la documentación de la clase (en este ejemplo, FreeSpace y Size son uint649) y convertirlas en consecuencia. El primer tropiezo habitual es asumir que es int y convertir así, lo que produce InvalidCastException.

La trampa de obtener propiedades y convertirlas de tipoEn System.Management las propiedades se devuelven como object a través del indexador por lo que hay que comprobar el tipo CIM en la documentación de la clase antes de convertirlas, si se asume erróneamente que es int la conversión produce InvalidCastExceptionObtención con el indexadorSe devuelve como objectComprobar el tipo CIM en la documentaciónConversión al tipo correctoSe asume int y se convierteInvalidCastException

Figura 8: Como las propiedades se devuelven como object, hay que comprobar el tipo CIM antes de convertirlas.

5.2. API MI: lo básico de CimSession

CimSession permite manejar lo local y lo remoto de la misma forma. Dispone de enumeración, consulta, llamada a métodos, suscripción a eventos y sus versiones asíncronas, todo en un mismo paquete. 6

// NuGet: Microsoft.Management.Infrastructure (exclusivo de Windows)
using Microsoft.Management.Infrastructure;

// Para local, CimSession.Create(null); para remoto, se pasa el nombre del equipo
using CimSession session = CimSession.Create(null);

IEnumerable<CimInstance> disks = session.QueryInstances(
    @"root\cimv2", "WQL",
    "SELECT DeviceID, FreeSpace, Size FROM Win32_LogicalDisk WHERE DriveType = 3");

foreach (CimInstance disk in disks)
{
    var deviceId = (string)disk.CimInstanceProperties["DeviceID"].Value;
    var free = (ulong)disk.CimInstanceProperties["FreeSpace"].Value;
    Console.WriteLine($"{deviceId} libre {free / 1024.0 / 1024 / 1024:F1} GB");
}

Como se maneja el mismo CimInstance que devuelven los cmdlets CIM de PowerShell, el flujo de desarrollo de «probar primero en PowerShell y luego trasladarlo a C#» encaja de forma natural. Si se va a diseñar la propia integración entre C# y PowerShell, consulte también «Cómo ejecutar PowerShell desde C# y recibir los resultados como objetos».

El flujo de probar en PowerShell y trasladarlo a C#Como los cmdlets CIM de PowerShell y la API MI de C# manejan el mismo tipo CimInstance, el flujo de desarrollo de prototipar en PowerShell y luego trasladarlo a C# encaja de forma naturalPrototipo en PowerShellCmdlets CIMImplementación final en C#API MIMismo tipo CimInstanceEl traslado encaja de forma natural

Figura 9: Como los cmdlets CIM y la API MI manejan el mismo tipo CimInstance, el prototipo enlaza directamente con la implementación final.

6. Recetas prácticas de uso habitual

6.1. Tabla de referencia rápida de clases habituales

Información deseada Clase Propiedades principales
Fabricante y modelo Win32_ComputerSystem Manufacturer, Model
Número de serie del equipo Win32_BIOS SerialNumber
Versión del SO y hora de arranque Win32_OperatingSystem Caption, Version, LastBootUpTime
Espacio libre en disco Win32_LogicalDisk DeviceID, FreeSpace, Size, DriveType9
Estado del servicio Win32_Service Name, State, StartMode
Lista de procesos Win32_Process Name, ProcessId, CommandLine

6.2. Lo habitual en gestión de activos: número de serie, modelo y espacio en disco

# Información del modelo y número de serie (para cotejar con el inventario de equipos)
$cs   = Get-CimInstance -ClassName Win32_ComputerSystem -Property Manufacturer, Model
$bios = Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber
[pscustomobject]@{
    Manufacturer = $cs.Manufacturer
    Model        = $cs.Model
    Serial       = $bios.SerialNumber
}

# Espacio libre en los discos locales (DriveType = 3)
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType = 3" |
    Select-Object DeviceID,
        @{ Name = 'FreeGB'; Expression = { [math]::Round($_.FreeSpace / 1GB, 1) } },
        @{ Name = 'SizeGB'; Expression = { [math]::Round($_.Size / 1GB, 1) } }

DriveType = 3 es el valor que representa «disco local», y excluye las unidades extraíbles (2), las unidades de red (4) y las de CD (5). 9 Para la monitorización, basta con ejecutar este script en cada servidor a través de una sesión CIM para tener la base de una monitorización de disco sin agente.

La base de la monitorización de disco sin agenteAl filtrar por DriveType 3 se excluyen las unidades extraíbles de red y de CD dejando solo los discos locales, al ejecutar el mismo script en cada servidor a través de una sesión CIM se obtiene la base de una monitorización de disco sin agenteScript de obtención de espacio libreFiltrar por DriveType = 3Excluye unidades extraíbles, etc.A través de una sesión CIMSe ejecuta en cada servidorMonitorización sin agente

Figura 10: La base de la monitorización consiste en ejecutar, mediante una sesión CIM, un script centrado en discos locales en cada servidor.

6.3. Detección del inicio de procesos ── Suscripción a eventos

En lugar de «obtener periódicamente Win32_Process mediante sondeo y comparar las diferencias», use la suscripción a eventos. Lo más sencillo es suscribirse a Win32_ProcessStartTrace (una clase de evento del proveedor de rastreo del núcleo que tiene propiedades como ProcessName, ProcessID y ParentProcessID8) para detectar el inicio de un proceso.

# Ejecutar en una sesión de PowerShell con privilegios de administrador
$action = {
    $name = $Event.SourceEventArgs.NewEvent.ProcessName
    $id   = $Event.SourceEventArgs.NewEvent.ProcessID
    Write-Host "Proceso iniciado: $name (PID=$id)"
}
Register-CimIndicationEvent -ClassName Win32_ProcessStartTrace `
    -SourceIdentifier ProcessStarted -Action $action

La suscripción permanece activa mientras viva la sesión de PowerShell donde se hizo el registro, y -Action se ejecuta cada vez que se inicia un proceso. Tenga cuidado de no ejecutar de corrido el comando de cancelación justo después: la suscripción desaparecería antes de que empiece la monitorización. La cancelación se ejecuta cuando se termina la monitorización.

# Al terminar la monitorización: cancelar la suscripción
Unregister-Event -SourceIdentifier ProcessStarted

Register-CimIndicationEvent registra la suscripción con el nombre de la clase o con una consulta de evento WQL, y el bloque de script de -Action se ejecuta cada vez que llega un evento. 7 La suscripción a esta clase requiere privilegios de administrador. 7 Quién puede recibir el evento está controlado por el descriptor de seguridad de la clase de evento, y con un usuario estándar se obtiene un acceso denegado. 8

Flujo de la suscripción al evento de inicio de procesoEn una sesión de PowerShell con privilegios de administrador Register-CimIndicationEvent registra la suscripción, cada vez que se inicia un proceso llega el evento y se ejecuta Action, y al terminar la monitorización se cancela con Unregister-EventWMISesión de PowerShellWMISesión de PowerShellSe ejecuta con privilegios de administradorRegistra la suscripción con Register-CimIndicationEventLlega un evento cada vez que se inicia un procesoEjecuta -ActionCancela con Unregister-Event (al finalizar la monitorización)

Figura 11: La suscripción permanece activa mientras viva la sesión que la registró, y la cancelación se hace al terminar la monitorización.

Otro método es el evento genérico de creación de instancia (__InstanceCreationEvent), utilizable con cualquier clase. En este caso, WMI sondea con el intervalo indicado en WITHIN y convierte las diferencias en eventos, así que hay que decidir uno mismo el equilibrio entre el intervalo de detección y la carga.

Dos métodos de suscripción para detectar el inicio de procesosWin32_ProcessStartTrace es un método que se suscribe a la clase de evento del proveedor de rastreo del núcleo, el genérico __InstanceCreationEvent hace que WMI sondee con el intervalo indicado en WITHIN y convierta las diferencias en eventos por lo que hay que decidir uno mismo el equilibrio entre el intervalo de detección y la cargaDetección del inicio de procesosWin32_ProcessStartTrace__InstanceCreationEventSuscripción al rastreo del núcleoSondeo con intervalo WITHINEquilibrio entre intervalo y carga

Figura 12: Suscribirse a la clase de evento dedicada o usar el evento genérico de creación de instancia con un intervalo de sondeo.

# Monitorizar nuevas instancias de Win32_Process con un sondeo de 5 segundos
$query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process'"
Register-CimIndicationEvent -Query $query -SourceIdentifier ProcPoll -Action {
    Write-Host "Iniciado: $($Event.SourceEventArgs.NewEvent.TargetInstance.Name)"
}

En C# (System.Management), ManagementEventWatcher cumple el mismo papel. 11

using System.Management;

// En un proceso que se ejecute como administrador
var watcher = new ManagementEventWatcher(
    new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
watcher.EventArrived += (_, e) =>
{
    var name = (string)e.NewEvent["ProcessName"];
    var pid  = (uint)e.NewEvent["ProcessID"];
    Console.WriteLine($"Proceso iniciado: {name} (PID={pid})");
};
watcher.Start();
// Al terminar la monitorización, no olvide watcher.Stop() y Dispose

Si se incorpora a una monitorización permanente, incluya en el diseño el reingreso de la suscripción cuando esta se interrumpa (al reiniciar el servicio o ante un error). La teoría de diseño de «comprobación y presentación del estado», que incluye la monitorización de dispositivos, se trata en «Buenas prácticas para comprobar y mostrar el estado de dispositivos externos».

Ciclo de vida de la suscripción en una monitorización permanenteEn una monitorización permanente el estado de suscripción activa puede interrumpirse por un reinicio del servicio o un error, así que el diseño debe incluir la detección de esa interrupción y el reingreso a la suscripción activaReinicio del servicio / errorSuscripción activaSuscripción interrumpidaReingreso

Figura 13: En la monitorización permanente, el diseño debe contemplar el reingreso a la suscripción activa cuando esta se interrumpe.

7. Trampas habituales ── Rendimiento, permisos, 64 bits, repositorio y fechas

7.1. El abuso de SELECT * y del sondeo (polling)

Una consulta WMI es un proceso en el que «el proveedor genera los valores en el momento», y eso tiene un coste. Hay dos antipatrones habituales.

  • El uso perezoso de SELECT *. Obtener todos los registros de Win32_Process con todas sus propiedades aumenta tanto el trabajo del proveedor como la transferencia por red (en el caso remoto). Filtre las filas con -Filter y las columnas con -Property, y si solo necesita las claves para una operación posterior, use -KeyOnly. Todas son herramientas oficiales pensadas «para reducir el tamaño de los objetos y el tráfico de red». 3
  • El sondeo de ciclo corto. Un diseño como «Get-CimInstance Win32_Process cada segundo» debe sustituirse por la suscripción a eventos del apartado 6.3. Si de todos modos se usa el tipo de sondeo (WITHIN), amplíe el intervalo hasta el mínimo suficiente para el requisito.

Además, repetir -ComputerName equipo por equipo contra destinos remotos también es una forma muy ineficiente: se crea una sesión temporal en cada consulta. Cambie las operaciones múltiples a reutilizar una sesión CIM. 3

Antipatrones de rendimiento y sus sustitutosEl uso perezoso de SELECT asterisco se sustituye filtrando filas y columnas con Filter y Property y usando KeyOnly si solo se necesitan las claves, el sondeo de ciclo corto se sustituye por la suscripción a eventos, y la repetición de ComputerName equipo por equipo se sustituye por la reutilización de una sesión CIMUso perezoso de SELECT *Filtrar con Filter y PropertySolo claves: usar KeyOnlySondeo de ciclo cortoSustituir por suscripción a eventosComputerName equipo por equipoReutilizar una sesión CIM

Figura 14: Filtrar filas, columnas y claves, y sustituir el sondeo por la suscripción a eventos, previene la mitad de los problemas de rendimiento de WMI.

7.2. Permisos para la suscripción a eventos

Como se explicó en el apartado 6.3, la suscripción a la familia Win32_ProcessStartTrace requiere privilegios de administrador. 7 El incidente de «funcionaba en la máquina de desarrollo (ejecutada como administrador), pero la monitorización no funciona en el entorno de usuario estándar del cliente» es tan habitual como el del cuadro de diálogo de notificación del firewall. Si se va a incorporar monitorización a una aplicación empresarial que se ejecuta como usuario estándar, considere separar la parte de monitorización en un servicio de Windows (por ejemplo, con LocalSystem) y conectarla con la aplicación principal mediante comunicación entre procesos.

Configuración de la monitorización en un entorno de usuario estándarLa suscripción que requiere privilegios de administrador se separa de la aplicación principal que se ejecuta como usuario estándar, aislando la parte de monitorización en un servicio de Windows que se ejecuta como LocalSystem por ejemplo, y conectándola con la aplicación principal mediante comunicación entre procesosComunicación entre procesosServicio de Windows de monitorizaciónSe suscribe al rastreo de inicioSe ejecuta como LocalSystem, etc.Aplicación principal(usuario estándar)

Figura 15: La suscripción que requiere privilegios de administrador se aísla en el servicio y se conecta con la aplicación principal mediante comunicación entre procesos.

7.3. Proveedores de 32 bits y 64 bits

En Windows de 64 bits, algunos proveedores tienen versiones de 32 y 64 bits que coexisten, y por defecto responde el lado que coincide con los bits de la aplicación que llama. 12 Un caso típico es el proveedor del registro de root\default (StdRegProv): al leerlo desde una aplicación de 32 bits, se devuelve el valor del lado Wow6432Node (la vista de 32 bits). 12 Cuando «el valor del registro leído por WMI es distinto del que se ve en regedit», sospeche de esto en primer lugar. Si se necesita la vista contraria, se puede solicitar explícitamente indicando __ProviderArchitecture (y, si se quiere hacer obligatorio, __RequiredArchitecture) en el contexto de la conexión. 12 El panorama general del problema de los bits también se trata en «Llamar de forma segura a la API de Win32 desde C# ── Guía práctica de P/Invoke».

Selección de proveedor en un entorno de 64 bitsPor defecto responde el proveedor cuyo número de bits coincide con el de la aplicación que llama, una consulta de registro desde una aplicación de 32 bits recibe el valor del lado Wow6432Node, pero indicando __ProviderArchitecture se puede solicitar explícitamente la vista contraria32 bits64 bits¿Cuántos bits tiene el llamador?Responde el proveedor de 32 bitsResponde el proveedor de 64 bitsEl registro es el valor del lado Wow6432NodeIndicar __ProviderArchitectureSolicita explícitamente la vista contraria

Figura 16: Por defecto responde el lado que coincide con los bits del llamador, así que una aplicación de 32 bits lee el lado Wow6432Node.

7.4. Síntomas y solución cuando el repositorio de WMI se corrompe

Las definiciones de las clases de WMI se guardan en un repositorio (no es un único archivo: el conjunto de archivos de la carpeta Repository funciona como base de datos13). Cuando este repositorio se vuelve incoherente, empiezan a aparecer errores como «no se encuentra una clase que debería existir» o «espacio de nombres no válido», aunque no se haya cambiado nada en la aplicación. Para diagnosticar y reparar se usa winmgmt.exe. 13

rem Comprobación de coherencia (si el resultado es inconsistent, hay incoherencia)
winmgmt /verifyrepository

rem Comprobación de coherencia + reconstrucción si hay incoherencia (lo que se puede leer se fusiona)
winmgmt /salvagerepository

Lo importante es no recurrir a eliminar o reinicializar el repositorio como primer paso. Los errores que aparecen a través de WMI a veces tienen su origen en otra parte del sistema operativo, y Microsoft advierte explícitamente que eliminar el repositorio como primer tratamiento «puede provocar daños al sistema o a las aplicaciones instaladas». 13 Respete el orden: comprobar con /verifyrepository → reparar con /salvagerepository.

Procedimiento de diagnóstico ante una incoherencia del repositorio de WMISi aparecen errores como que no se encuentra una clase se comprueba la coherencia con winmgmt verifyrepository, si hay incoherencia se reconstruye con salvagerepository, y no se recurre a eliminar o reinicializar el repositorio como primer pasoNoError como «clase no encontrada»winmgmt /verifyrepository¿El resultado es inconsistent?winmgmt /salvagerepositorySospechar de otra parte del SOLo que se puede leer se fusionaEliminar o reinicializar el repositorioNo como primer paso

Figura 17: Respete el orden de comprobar con verify y reparar con salvage, y no elimine el repositorio como primer paso.

7.5. Conversión del formato de fecha DMTF

Las fechas de WMI se almacenan como una cadena en el formato DMTF de la especificación CIM, yyyymmddHHMMSS.mmmmmm±UUU (el sufijo es el desfase en minutos respecto a UTC; por ejemplo, 20260801100000.000000+540). No manipule el valor en bruto con procesamiento de cadenas: use la API de conversión.

  • C# (System.Management): ManagementDateTimeConverter ofrece la conversión mutua entre el formato DMTF y DateTime / TimeSpan. 11
  • API de la familia CIM (Get-CimInstance / API MI): la propiedad de fecha se devuelve ya convertida a DateTime, así que este problema ni siquiera se presenta. (Get-CimInstance Win32_OperatingSystem).LastBootUpTime se puede usar directamente como DateTime en los cálculos.
Tratamiento del formato de fecha DMTFLas fechas de WMI se almacenan como una cadena en formato DMTF, si se lee el valor en bruto con System.Management se convierte con ManagementDateTimeConverter, si es una API de la familia CIM se devuelve ya convertida a DateTime, por lo que no se manipula la cadena a manoSystem.ManagementAPI de la familia CIMCadena en formato DMTF¿Con qué API se obtiene?ManagementDateTimeConverterSe devuelve ya convertida a DateTimeConversión a DateTime / TimeSpanManipular la cadena a manoNo se usa

Figura 18: Deje la conversión de la cadena DMTF a la API de conversión; con una API de la familia CIM, use directamente el DateTime ya convertido.

8. Casos en los que no conviene usar WMI ── Tabla de decisión de medios

WMI es excelente como «punto de lectura unificado», pero no siempre es la solución óptima. A continuación, una guía práctica para elegir entre las distintas opciones.

Qué se quiere hacer Medio adecuado Por qué no elegir WMI
Obtener información de hardware y configuración del SO, consultas remotas sin agente WMI/CIM Aquí es donde WMI brilla de verdad. Más unificado que llamar a API específicas por separado
Lectura y escritura de la configuración de la propia aplicación Lectura directa del registro (Microsoft.Win32.Registry), archivos de configuración Manipular el registro a través de WMI es un rodeo y arrastra también el problema de bits del apartado 7.3
Monitorización de rendimiento de alta frecuencia y continua, como el uso de CPU Contadores de rendimiento (System.Diagnostics.PerformanceCounter, etc.) Los contadores existen precisamente para eso. El sondeo de ciclo corto de WMI es peor en carga y precisión
Llamadas puntuales a funciones del SO, procesos que necesitan baja latencia API de Win32 (P/Invoke) WMI tiene la sobrecarga de pasar por COM/el proveedor
Enumeración y manejo local de procesos que basta hacer con los permisos del propio proceso System.Diagnostics.Process Se resuelve con la biblioteca estándar y reduce dependencias
Configuración de funciones de administración de Windows como el firewall o la red Cmdlets dedicados basados en CIM, como Get-NetFirewallRule Un conjunto de cmdlets preparado por finalidad es más preciso y seguro que buscar la clase de WMI en bruto
Detección de cambios en archivos y carpetas FileSystemWatcher No lleve WMI a un terreno que ya tiene una API dedicada

El eje de decisión es simple: «usar el mecanismo dedicado donde exista uno, y usar WMI/CIM para las consultas transversales y remotas». Los cmdlets de la última fila, como Get-NetFirewallRule, están internamente construidos sobre CIM, así que se puede decir que son una forma de «aprovechar las ventajas de WMI/CIM sin tocarlo directamente».

El eje de decisión sobre los mediosEl eje de decisión es usar el mecanismo dedicado en las áreas donde existe uno, y usar WMI y CIM para las consultas transversales o remotas en las áreas donde no lo hay, los cmdlets dedicados basados en CIM son una forma de aprovechar sus ventajas sin tocar WMI y CIM directamenteNo¿Existe un mecanismo dedicado?Usar el mecanismo dedicadoUsar WMI / CIMConsultas transversales y remotasCmdlets dedicados basados en CIMAprovechar solo las ventajas

Figura 19: En las áreas con un mecanismo dedicado, úselo; para las consultas transversales y remotas, use WMI/CIM.

9. Resumen

  • CIM es el estándar de la industria del DMTF, y WMI es su implementación de Microsoft. Tanto los cmdlets CIM de PowerShell como la API MI de C# son puntos de entrada de la generación actual que siguen ese estándar.
  • En PowerShell, lo actual son Get-CimInstance / Invoke-CimMethod / Register-CimIndicationEvent. Como los cmdlets WMI, como Get-WmiObject, no existen en PowerShell 7, los scripts nuevos se escriben con CIM aunque estén orientados a 5.1.
  • WSMan (WinRM) es el predeterminado para las consultas remotas, y las operaciones múltiples reutilizan una sesión CIM. Para los destinos sin WinRM configurado existe la salida de la opción DCOM.
  • En C# se elige entre dos líneas: System.Management (sencilla, orientada a lo local) y Microsoft.Management.Infrastructure (orientada a lo remoto y a la monitorización, con el mismo sistema de tipos que los cmdlets CIM). Ambas son paquetes NuGet exclusivos de Windows.
  • Monitorice los procesos con suscripción a eventos, no con sondeo. La suscripción a Win32_ProcessStartTrace requiere privilegios de administrador.
  • Evite SELECT * y el sondeo de ciclo corto; filtre con -Filter / -Property / -KeyOnly. Recuerde que una consulta desde un proceso de 32 bits se dirige al proveedor de 32 bits, que las fechas DMTF deben tratarse con la API de conversión, y que una incoherencia del repositorio se trata con el orden verify → salvage, no con la eliminación.
  • No lleve WMI a las áreas que ya tienen un mecanismo dedicado (configuración, contadores de rendimiento, llamadas puntuales a API); use WMI/CIM para las consultas transversales y remotas ── esa es, en una frase, la clave de cuándo usarlo.

Artículos relacionados

Áreas de consultoría relacionadas

KomuraSoft LLC se ocupa de incorporar a aplicaciones empresariales la obtención de información de hardware, la monitorización de procesos y la consulta de PC remotos mediante WMI/CIM, de migrar scripts internos basados en Get-WmiObject a los cmdlets CIM, y de investigar el tipo de causa detrás de «funciona en la máquina de desarrollo, pero da un error de permisos en el cliente». Puede consultarnos de forma continua, desde el prototipo en PowerShell hasta la implementación final en C#.

Referencias

  1. Microsoft Learn, About WMI. Sobre que WMI es la implementación de Microsoft de WBEM (una iniciativa de la industria que desarrolla la tecnología estándar para el acceso a la información de administración en entornos empresariales); que usa el estándar de la industria CIM (Common Information Model) para representar los objetos administrados, y que el CIM lo desarrolla y mantiene el DMTF (Distributed Management Task Force); que la versión de próxima generación MI (Windows Management Infrastructure) es totalmente compatible con el WMI tradicional; y que la conexión remota a WMI se realiza por DCOM, existiendo como alternativa WinRM basado en WS-Management.  2 3 4 5

  2. Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. Sobre que los cmdlets WMI v1 (Register-WmiEvent, Set-WmiInstance, Invoke-WmiMethod, Get-WmiObject, Remove-WmiObject) se eliminaron de PowerShell, y que los cmdlets del módulo CimCmdlets (WMI v2) ofrecen la misma funcionalidad con nuevas características y una sintaxis rediseñada.  2

  3. Microsoft Learn, Get-CimInstance (CimCmdlets). Sobre que, si no se indica ni ComputerName ni CimSession, se conecta al WMI local con una sesión COM, y que al indicar -ComputerName se crea una sesión temporal con el protocolo WsMan; que para varias operaciones sobre el mismo equipo se recomienda por rendimiento conectar con una sesión CIM; que -Filter es la cláusula where de WQL/CQL sin la palabra clave WHERE; que -Property y -KeyOnly permiten reducir el tamaño del objeto y el tráfico de red; que el espacio de nombres predeterminado es root/CIMV2 y el lenguaje de consulta predeterminado (-QueryDialect) es WQL; que la salida es Microsoft.Management.Infrastructure.CimInstance; un ejemplo de llamada a GetOwner combinado con Invoke-CimMethod; y que es un cmdlet exclusivo de Windows.  2 3 4 5 6 7 8 9 10

  4. Microsoft Learn, New-CimSessionOption (CimCmdlets). Sobre que las opciones de sesión CIM tienen dos conjuntos de parámetros, uno para WsMan y otro para DCOM; que -Protocol admite Dcom / Default / Wsman; un ejemplo de creación de una sesión CIM por DCOM pasando a -SessionOption de New-CimSession la opción creada con New-CimSessionOption -Protocol Dcom; y que el nivel de suplantación predeterminado de una sesión DCOM es Impersonate.  2

  5. Microsoft Learn, ManagementObjectSearcher Class (System.Management). Sobre que es la clase de entrada más habitual para obtener información de administración, ya que recupera una colección de objetos administrados según la consulta WQL indicada; que recibe un ObjectQuery y un ManagementScope (el espacio de nombres de WMI) y devuelve un ManagementObjectCollection con Get(); y que System.Management.dll se distribuye como el paquete NuGet System.Management.  2 3 4

  6. Microsoft Learn, CimSession Class (Microsoft.Management.Infrastructure). Sobre que Microsoft.Management.Infrastructure.dll se distribuye como el paquete NuGet Microsoft.Management.Infrastructure; la creación de sesiones con Create(computerName); la ejecución de consultas con QueryInstances(namespace, queryDialect, query); y que dispone de EnumerateInstances / GetInstance / InvokeMethod / Subscribe junto con sus versiones asíncronas respectivas (*Async), e implementa IDisposable.  2 3 4 5

  7. Microsoft Learn, Register-CimIndicationEvent (CimCmdlets). Sobre que se suscribe a una indicación (evento) mediante el nombre de la clase o una expresión de consulta, asignando el nombre de la suscripción con -SourceIdentifier; un ejemplo de suscripción a Win32_ProcessStartTrace y la nota de que su ejecución requiere ejecutar PowerShell como administrador; un ejemplo de referencia a ProcessName / ProcessId desde $Event.SourceEventArgs.NewEvent dentro del bloque de script de -Action; que al indicar -ComputerName se conecta con una sesión temporal WsMan, y sin indicarlo se conecta localmente por COM; y que se usa Unregister-Event para cancelar la suscripción.  2 3 4

  8. Microsoft Learn, Win32_ProcessStartTrace class. Sobre que es una clase de evento que indica el inicio de un proceso nuevo y tiene propiedades como ProcessName, ProcessID, ParentProcessID, SessionID y Sid; que la propiedad SECURITY_DESCRIPTOR es el descriptor que usa el proveedor del evento para decidir qué usuario puede recibirlo; y que el espacio de nombres es Root\CIMV2 y lo aporta el proveedor de rastreo del núcleo (Krnlprov.dll).  2 3

  9. Microsoft Learn, Win32_LogicalDisk class. Sobre que Win32_LogicalDisk es una clase derivada de CIM_LogicalDisk que representa un dispositivo de almacenamiento local; los valores de DriveType (2 = extraíble, 3 = disco local, 4 = unidad de red, 5 = CD, etc.); que FreeSpace y Size son valores en bytes de tipo uint64; que DeviceID es la clave; y ejemplos de consulta en VBScript / C# que filtran por DriveType = 3.  2 3 4

  10. Microsoft Learn, Installation and configuration for Windows Remote Management. Sobre que, por defecto, el agente de escucha de WinRM no está configurado y no se pueden enviar ni recibir mensajes WS-Management; que winrm quickconfig realiza el arranque automático del servicio, la configuración del agente de escucha HTTP/HTTPS y el registro de la excepción del firewall; que los puertos predeterminados de WinRM 2.0 son HTTP 5985 y HTTPS 5986; que, cuando no se puede establecer la autenticación mutua (Kerberos), como en un grupo de trabajo, hay que configurar TrustedHosts limitándolo en la medida de lo posible; y sobre el descriptor de seguridad predeterminado (RootSDDL) que controla el acceso remoto al agente de escucha, así como la configuración adicional necesaria para permitir el uso del complemento de WMI a usuarios que no sean administradores.  2 3 4

  11. Microsoft Learn, System.Management Namespace. Sobre que es el espacio de nombres que realiza las consultas a la infraestructura de WMI mediante las clases de la familia ManagementObjectSearcher y la suscripción a eventos mediante ManagementEventWatcher; que WqlEventQuery representa una consulta de evento en formato WQL; y que ManagementDateTimeConverter ofrece métodos de conversión mutua entre las fechas e intervalos DMTF y los DateTime / TimeSpan del CLR.  2 3

  12. Microsoft Learn, Requesting WMI Data on a 64-bit Platform. Sobre que, cuando coexisten una versión de 32 bits y otra de 64 bits de un proveedor, por defecto responde el proveedor de 32 bits a las aplicaciones de 32 bits (incluidos los scripts) y el de 64 bits a las de 64 bits; que con __ProviderArchitecture (32 o 64) y __RequiredArchitecture en el contexto se puede solicitar o exigir el proveedor del lado no predeterminado (si se exige y no existe esa versión, se produce WBEM_E_PROVIDER_LOAD_FAILURE); y, como ejemplo con el proveedor del registro, que un cliente de 32 bits recibe los datos del lado HKLM\SOFTWARE\Wow6432Node.  2 3

  13. Microsoft Learn, winmgmt. Sobre que /verifyrepository de winmgmt.exe comprueba la coherencia del repositorio de WMI; que /salvagerepository, además de comprobar la coherencia, reconstruye el repositorio si detecta una incoherencia y fusiona el contenido que se pudo leer; que /resetrepository devuelve el repositorio al estado de la instalación inicial del sistema operativo; que el repositorio funciona como base de datos mediante el conjunto de archivos de la carpeta Repository; y que, como los errores producidos a través de WMI a veces se originan en otra parte del sistema operativo, no se debe eliminar el repositorio como primer tratamiento, ya que puede provocar daños al sistema o a las aplicaciones instaladas.  2 3

Artículos recientes con las mismas etiquetas para profundizar en temas cercanos.

Estas páginas sitúan el tema en un contexto más amplio de servicios y decisiones.

El artículo está directamente relacionado con los siguientes servicios.

Preguntas frecuentes

Preguntas habituales en las consultas sobre el tema del artículo.

¿Cuál es la diferencia entre WMI y CIM?
CIM es el «modelo estándar de la industria para representar objetos administrados, como sistemas y dispositivos», definido y mantenido por el DMTF (Distributed Management Task Force). WMI es la implementación de Microsoft de esa norma dentro de la iniciativa WBEM, y viene integrado en Windows. Es decir, CIM es la especificación y WMI es su implementación en Windows. El motivo de que Get-CimInstance en PowerShell o Microsoft.Management.Infrastructure en C# se llamen «CIM» es que son API que siguen ese estándar, pero el destino de la conexión sigue siendo la misma infraestructura de WMI. Para el trabajo diario basta con entender que «se consultan las clases de WMI (como Win32_*) mediante las API de la familia CIM».
¿Ya no se puede usar Get-WmiObject?
En Windows PowerShell 5.1 todavía funciona, pero desde PowerShell 6 en adelante (la versión actual, PowerShell 7) los cmdlets WMI v1 —Get-WmiObject, Invoke-WmiMethod, Register-WmiEvent, Set-WmiInstance y Remove-WmiObject— han sido eliminados y no se pueden ejecutar. La misma funcionalidad la ofrece el módulo CimCmdlets (Get-CimInstance, Invoke-CimMethod, Register-CimIndicationEvent, etc.). Para los scripts nuevos, lo más seguro es escribirlos con los cmdlets CIM aunque vayan a ejecutarse en 5.1. De ese modo, no habrá que reescribir la parte de WMI cuando se migre a PowerShell 7.
Para usar WMI desde C#, ¿debo usar System.Management o Microsoft.Management.Infrastructure?
Ambas son exclusivas de Windows y, desde el .NET actual, se usan como paquetes NuGet. System.Management es la API clásica: basta con pasar WQL a ManagementObjectSearcher, y es suficiente si el objetivo principal es obtener información local. También incluye ManagementDateTimeConverter, que convierte las fechas DMTF. Por otro lado, Microsoft.Management.Infrastructure (la API MI) comparte el mismo sistema de tipos que los cmdlets CIM de PowerShell (CimSession / CimInstance) y permite manejar de forma coherente las consultas remotas por WSMan, las versiones asíncronas de los métodos e incluso la suscripción a eventos (Subscribe). Si se va a incorporar de forma seria la consulta o la monitorización de PC remotos, lo razonable es elegir la API MI.
Get-CimInstance no se conecta a un PC remoto. ¿Qué debo comprobar?
Primero compruebe si WinRM está configurado en el equipo de destino. Las operaciones CIM con -ComputerName crean una sesión temporal mediante el protocolo WSMan (WinRM), por lo que se da por hecho que el servicio WinRM y su agente de escucha están activos en el destino. Con winrm quickconfig se puede realizar la configuración predeterminada (inicio del servicio, creación del agente de escucha y registro de la excepción en el firewall). Los puertos predeterminados son 5985 para HTTP y 5986 para HTTPS, así que compruebe también el firewall del trayecto. En un entorno de grupo de trabajo no se puede usar la autenticación mutua Kerberos, por lo que puede ser necesario registrar el destino en TrustedHosts del lado cliente. Si de ningún modo se puede configurar WinRM en el destino, otra opción es conectar por DCOM usando las opciones creadas con New-CimSessionOption -Protocol Dcom.
¿Por qué las fechas de WMI se devuelven en un formato como «20260801100000.000000+540»?
Porque las fechas de WMI se almacenan en el formato de cadena definido por la especificación CIM del DMTF (yyyymmddHHMMSS.mmmmmm±UUU, donde el sufijo es el desfase en minutos respecto a UTC). Si se lee el valor en bruto con el antiguo Get-WmiObject o con System.Management, se obtiene esta cadena tal cual. En C# (System.Management), ManagementDateTimeConverter ofrece métodos para convertir entre el formato DMTF y DateTime / TimeSpan, así que utilícelos en lugar de manipular la cadena a mano. Además, si se obtiene el dato con una API de la familia CIM, como Get-CimInstance, la propiedad de fecha ya se devuelve convertida a DateTime, por lo que este problema ni siquiera se presenta.

Perfil del autor

Página de presentación del autor del artículo.

Go Komura

Representante de KomuraSoft LLC

Especializado en desarrollo de software para Windows, consultoría técnica e investigación de fallos, sobre todo en proyectos con sistemas existentes y errores difíciles de reproducir.

Volver al blog