Compartir a través de


Capítulo 7: Trabajar con WMI

WMI y CIM

Windows PowerShell viene de forma predeterminada con cmdlets para trabajar con otras tecnologías, como Instrumentación de administración de Windows (WMI). Los cmdlets de WMI están en desuso y no están disponibles en PowerShell 6 y versiones posteriores, pero se tratan aquí, ya que podría encontrarse con ellos en scripts anteriores que se ejecutan en Windows PowerShell. Para nuevos desarrollos, use los cmdlets CIM en su lugar.

Existen varios cmdlets WMI nativos en PowerShell sin tener que instalar ningún otro software o módulo. Get-Command se puede usar para determinar qué cmdlets WMI existen en Windows PowerShell. Los siguientes resultados proceden de un sistema Windows 11 que ejecuta PowerShell versión 5.1. Los resultados pueden diferir en función de la versión de PowerShell que esté ejecutando.

Get-Command -Noun WMI*
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Get-WmiObject                                      3.1.0.0
Cmdlet          Invoke-WmiMethod                                   3.1.0.0
Cmdlet          Register-WmiEvent                                  3.1.0.0
Cmdlet          Remove-WmiObject                                   3.1.0.0
Cmdlet          Set-WmiInstance                                    3.1.0.0

Los cmdlets de Common Information Model (CIM) se introdujeron en PowerShell 3.0 y se agrupan en un módulo dedicado. Para enumerar todos los cmdlets CIM disponibles, use el Get-Command cmdlet con el parámetro Module , como se muestra en el ejemplo siguiente.

Get-Command -Module CimCmdlets
CommandType     Name                                               Version
-----------     ----                                               -------
Cmdlet          Export-BinaryMiLog                                 1.0.0.0
Cmdlet          Get-CimAssociatedInstance                          1.0.0.0
Cmdlet          Get-CimClass                                       1.0.0.0
Cmdlet          Get-CimInstance                                    1.0.0.0
Cmdlet          Get-CimSession                                     1.0.0.0
Cmdlet          Import-BinaryMiLog                                 1.0.0.0
Cmdlet          Invoke-CimMethod                                   1.0.0.0
Cmdlet          New-CimInstance                                    1.0.0.0
Cmdlet          New-CimSession                                     1.0.0.0
Cmdlet          New-CimSessionOption                               1.0.0.0
Cmdlet          Register-CimIndicationEvent                        1.0.0.0
Cmdlet          Remove-CimInstance                                 1.0.0.0
Cmdlet          Remove-CimSession                                  1.0.0.0
Cmdlet          Set-CimInstance                                    1.0.0.0

Los cmdlets CIM aún te permiten trabajar con WMI, por lo que no te confundas cuando alguien indique: "Cuando consultas WMI con los cmdlets CIM de PowerShell".

Como se mencionó anteriormente, WMI es una tecnología independiente de PowerShell y solo usa los cmdlets CIM para acceder a WMI. Es posible que encuentre un VBScript antiguo que use el lenguaje de consulta WMI (WQL) para consultar WMI, como en el ejemplo siguiente.

strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\CIMV2")

Set colBIOS = objWMIService.ExecQuery _
    ("Select * from Win32_BIOS")

For each objBIOS in colBIOS
    Wscript.Echo "Manufacturer: " & objBIOS.Manufacturer
    Wscript.Echo "Name: " & objBIOS.Name
    Wscript.Echo "Serial Number: " & objBIOS.SerialNumber
    Wscript.Echo "SMBIOS Version: " & objBIOS.SMBIOSBIOSVersion
    Wscript.Echo "Version: " & objBIOS.Version
Next

Puede tomar la consulta WQL desde VBScript y usarla con el Get-CimInstance cmdlet sin modificaciones.

Get-CimInstance -Query 'Select * from Win32_BIOS'
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 3810-1995-1654-4615-2295-2755-89
Version           : VRTUAL - 4001628

El ejemplo anterior no es cómo normalmente se consulta WMI con PowerShell. Pero funciona y permite migrar fácilmente scripts de Visual Basic existentes a PowerShell. Al escribir un solo liner para consultar WMI, uso la sintaxis siguiente.

Get-CimInstance -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 3810-1995-1654-4615-2295-2755-89
Version           : VRTUAL - 4001628

Si solo desea el número de serie, canalice la salida a Select-Object y especifique solo la propiedad SerialNumber .

Get-CimInstance -ClassName Win32_BIOS |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

De forma predeterminada, al consultar WMI, se recuperan en segundo plano varias propiedades que nunca se utilizan. No tiene mucha importancia al consultar WMI en el equipo local. Pero una vez que empiece a consultar computadoras remotas, no solo habrá un tiempo de procesamiento adicional para devolver esa información, sino también información innecesaria para enviar a través de la red. Get-CimInstance tiene un parámetro Property que limita la información recuperada, lo que hace que la consulta WMI sea más eficaz.

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -Property SerialNumber
SerialNumber
------------
3810-1995-1654-4615-2295-2755-89

Los resultados anteriores devolvieron un objeto . Para devolver una cadena, use el parámetro ExpandProperty .

Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber |
    Select-Object -ExpandProperty SerialNumber
3810-1995-1654-4615-2295-2755-89

También puede usar el estilo de sintaxis de puntos para devolver una cadena, lo que elimina la necesidad de canalizar a Select-Object.

(Get-CimInstance -ClassName Win32_BIOS -Property SerialNumber).SerialNumber
3810-1995-1654-4615-2295-2755-89

Consulta de equipos remotos con los cmdlets CIM

Todavía debe ejecutar PowerShell como administrador local y usuario de dominio. Al intentar consultar información desde un equipo remoto mediante el Get-CimInstance cmdlet , recibirá un mensaje de error de acceso denegado.

Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
Get-CimInstance : Access is denied.
At line:1 char:1
+ Get-CimInstance -ComputerName dc01 -ClassName Win32_BIOS
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : PermissionDenied: (root\cimv2:Win32_BIOS:Stri
   ng) [Get-CimInstance], CimException
    + FullyQualifiedErrorId : HRESULT 0x80070005,Microsoft.Management.Infra
   structure.CimCmdlets.GetCimInstanceCommand
    + PSComputerName        : dc01

Muchas personas tienen problemas de seguridad con respecto a PowerShell, pero tiene los mismos permisos en PowerShell que en la GUI. Ni más ni menos. El problema del ejemplo anterior es que el usuario que ejecuta PowerShell no tiene derechos para consultar información de WMI desde el servidor DC01. Puede volver a iniciar PowerShell como administrador de dominio, ya que Get-CimInstance no tiene un parámetro Credential . Pero eso no es una buena idea porque cualquier cosa que ejecute desde PowerShell se ejecutaría como administrador de dominio. En función de la situación, ese escenario podría ser peligroso desde el punto de vista de la seguridad.

Con el principio de privilegios mínimos, eleve a la cuenta de administrador de dominio por comando mediante el parámetro Credential si un comando tiene uno. Get-CimInstance no tiene un parámetro Credential , por lo que la solución en este escenario es crear primero cimSession . A continuación, use CimSession en lugar de un nombre de equipo para consultar WMI en el equipo remoto.

$CimSession = New-CimSession -ComputerName dc01 -Credential (Get-Credential)
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

La sesión CIM se almacenó en una variable denominada $CimSession. Tenga en cuenta que también especifica el Get-Credential cmdlet entre paréntesis para que se ejecute primero y solicite credenciales alternativas antes de crear la nueva sesión. Le mostré otra manera más eficaz de especificar credenciales alternativas más adelante en este capítulo, pero es importante comprender este concepto básico antes de que sea más complicado.

Ahora puede usar la sesión CIM creada en el ejemplo anterior con el Get-CimInstance cmdlet para consultar la información del BIOS de WMI en el equipo remoto.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 0986-6980-3916-0512-6608-8243-13
Version           : VRTUAL - 4001628
PSComputerName    : dc01

Existen otras ventajas para usar sesiones CIM en lugar de especificar un nombre de equipo. Cuando se ejecutan varias consultas en el mismo equipo, el uso de una sesión CIM es más eficaz que usar el nombre del equipo para cada consulta. La creación de una sesión CIM solo configura la conexión una vez. A continuación, varias consultas usan esa misma sesión para recuperar información. El uso del nombre del equipo requiere que los cmdlets configuren y desmonten la conexión en cada consulta.

El Get-CimInstance cmdlet usa el protocolo WSMan de forma predeterminada, lo que significa que el equipo remoto necesita PowerShell versión 3.0 o posterior para conectarse. En realidad, lo que importa no es la versión de PowerShell, sino la versión de la pila. Se puede determinar la versión de la pila utilizando el cmdlet Test-WSMan. Debe ser la versión 3.0, que se encuentra en PowerShell versión 3.0 y superiores.

Test-WSMan -ComputerName dc01
wsmid           : http://schemas.dmtf.org/wbem/wsman/identity/1/wsmanidentit
                  y.xsd
ProtocolVersion : http://schemas.dmtf.org/wbem/wsman/1/wsman.xsd
ProductVendor   : Microsoft Corporation
ProductVersion  : OS: 0.0.0 SP: 0.0 Stack: 3.0

Los cmdlets de WMI anteriores usan el protocolo DCOM, que es compatible con versiones anteriores de Windows. Sin embargo, el firewall normalmente bloquea DCOM en versiones más recientes de Windows. El New-CimSessionOption cmdlet permite crear una conexión de protocolo DCOM para su uso con New-CimSession. Esta opción permite al Get-CimInstance cmdlet comunicarse con versiones de Windows anteriores a Windows Server 2000. Esta capacidad también significa que PowerShell no es necesario en el equipo remoto cuando se usa el Get-CimInstance cmdlet con una CimSession configurada para usar el protocolo DCOM.

Cree la opción de protocolo DCOM mediante el New-CimSessionOption cmdlet y almacénela en una variable.

$DCOM = New-CimSessionOption -Protocol Dcom

Para mejorar la eficacia, puede almacenar el administrador de dominio o credenciales con privilegios elevados en una variable para que no tenga que escribirlas constantemente para cada comando.

$Cred = Get-Credential
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Credential

Tengo un servidor denominado SQL03 que ejecuta Windows Server 2008 (no R2). Es el sistema operativo Windows Server más reciente que no tiene PowerShell instalado de forma predeterminada.

Cree una cimSession en SQL03 mediante el protocolo DCOM.

$CimSession = New-CimSession -ComputerName sql03 -SessionOption $DCOM -Credential $Cred

Observe en el comando anterior que especifique la variable denominada $Cred como el valor del parámetro Credential en lugar de volver a escribir las credenciales manualmente.

La salida de la consulta es la misma independientemente del protocolo subyacente.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 7237-7483-8873-8926-7271-5004-86
Version           : VRTUAL - 4001628
PSComputerName    : sql03

El Get-CimSession cmdlet se usa para ver qué cimSessions están conectados actualmente y qué protocolos usan.

Get-CimSession
Id           : 1
Name         : CimSession1
InstanceId   : 80742787-e38e-41b1-a7d7-fa1369cf1402
ComputerName : dc01
Protocol     : WSMAN

Id           : 2
Name         : CimSession2
InstanceId   : 8fcabd81-43cf-4682-bd53-ccce1e24aecb
ComputerName : sql03
Protocol     : DCOM

Recupere y almacene las CimSessions creadas anteriormente en una variable denominada $CimSession.

$CimSession = Get-CimSession

Consulte ambos equipos con un comando, uno mediante el protocolo WSMan y el otro con DCOM.

Get-CimInstance -CimSession $CimSession -ClassName Win32_BIOS
SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 0986-6980-3916-0512-6608-8243-13
Version           : VRTUAL - 4001628
PSComputerName    : dc01

SMBIOSBIOSVersion : 090006
Manufacturer      : American Megatrends Inc.
Name              : Intel(R) Xeon(R) CPU E3-1505M v5 @ 2.80GHz
SerialNumber      : 7237-7483-8873-8926-7271-5004-86
Version           : VRTUAL - 4001628
PSComputerName    : sql03

Uno de mis artículos de blog sobre cmdlets WMI y CIM incluye una función de PowerShell que detecta automáticamente si se usa WSMan o DCOM y, a continuación, configura la sesión CIM adecuada automáticamente. Para obtener más información, consulte Función de PowerShell para crear CimSessions en equipos remotos con recurso a Dcom.

Cuando termine con las sesiones CIM, quítenlas con el Remove-CimSession cmdlet. Para quitar todas las sesiones CIM, canalice Get-CimSession a Remove-CimSession.

Get-CimSession | Remove-CimSession

Resumen

En este capítulo, ha aprendido a usar PowerShell para trabajar con WMI en equipos locales y remotos. También ha aprendido a usar los cmdlets CIM para trabajar con equipos remotos mediante los protocolos WSMan y DCOM.

Revisión

  1. ¿Cuál es la diferencia en los cmdlets WMI y CIM?
  2. De forma predeterminada, ¿qué protocolo usa el Get-CimInstance cmdlet?
  3. ¿Cuáles son algunas ventajas de usar una sesión CIM en lugar de especificar un nombre de equipo con Get-CimInstance?
  4. ¿Cómo se especifica un protocolo alternativo distinto del predeterminado para su uso con Get-CimInstance?
  5. ¿Cómo cierra o elimina sesiones CIM?

Referencias