PowerShell WMI: Automatizar tareas de Windows

La Instrumentación de Administración de Windows (WMI) ha existido durante mucho tiempo en Windows. Muchos profesionales de TI han utilizado WMI directamente o han empleado herramientas que leen información de WMI. ¿Sabías que los cmdlets de PowerShell para WMI están integrados de forma predeterminada?

WMI es el lugar por excelencia para recopilar información sobre una máquina con Windows y manipular diversos servicios dentro de Windows. Debido a la vasta cantidad de información de WMI, puedes aprovechar PowerShell para WMI. Utilizar PowerShell para interrogar WMI te permite automatizar miles de tareas en computadoras con Windows.

Afortunadamente, uno de los primeros sistemas en los que PowerShell tenía comandos era WMI. Dado que tienes cmdlets nativos de PowerShell para WMI, esto significaba que un administrador de TI podía aprovechar la sintaxis de PowerShell fácil de entender de verbo/sustantivo para interactuar con WMI y, como verás, los usuarios avanzados también pueden invocar eventos y clases de WMI directamente utilizando comandos estándar de PowerShell.

Cmdlets de PowerShell para WMI vs. CIM

Existen dos “conjuntos” de comandos cuando se trata de usar WMI en PowerShell. Algunas personas se refieren a estos “conjuntos” como la forma “antigua” de interactuar con WMI y los cmdlets de CIM. Al consultar información de WMI, ambos devuelven la misma información pero la abordan de manera un poco diferente. La forma “antigua” de leer información de WMI es mediante el uso del comando Get-WmiObject. Otros cmdlets de WMI incluyen Invoke-WmiMethod, Register-WMIEvent, etc., pero no los cubriremos en nuestro artículo.

El cmdlet de PowerShell WMI Get-WmiObject funciona pero tiene una seria desventaja. Al consultar equipos remotos, depende de DCOM y históricamente DCOM ha sido un vector de ataque para los malos. DCOM suele estar bloqueado por varios firewalls. Debido a que este es el “método antiguo”, no vamos a entrar en este método. En cambio, nos centraremos en los cmdlets CIM: principalmente, Get-CimInstance.

DCOM Component Services

La gran diferencia entre Get-WmiObject y Get-CimInstance es que en lugar de usar DCOM para acceder a equipos remotos, Get-CimInstance utiliza el protocolo WSMAN que es el transporte para la conocida característica de acceso remoto de PowerShell.

Cmdlets CIM de PowerShell

Supongamos que desea obtener información sobre la versión de Windows en un equipo remoto. En este caso, me gustaría ver información de un equipo llamado DC. Puede hacerlo especificando la clase WMI que contiene la información y el nombre del equipo que me gustaría consultar.

Puede ver a continuación que dado que Get-CimInstance no muestra, por defecto, todos los atributos dentro de la clase, he tenido que dirigir la salida al comando Select-Object para devolver todas las propiedades.

PS> Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName DC | Select *
Status                                    : OK
Name                                      : Microsoft Windows 10 Pro|C:\WINDOWS|\Device\Harddisk0\Partition2
FreePhysicalMemory                        : 1802336
FreeSpaceInPagingFiles                    : 800308
FreeVirtualMemory                         : 1472916
Caption                                   : Microsoft Windows 2016
Description                               :
InstallDate                               : 7/5/2018 6:04:09 PM
CreationClassName                         : Win32_OperatingSystem
CSCreationClassName                       : Win32_ComputerSystem
--snip-

No solo puedes obtener información a través de propiedades, sino que también puedes invocar métodos WMI/CIM en clases también. Un buen ejemplo de esto es detener un proceso en una computadora remota. Nativamente, no hay forma de hacer esto a través del comando Stop-Process en PowerShell. Sin embargo, hay una forma a través de una consulta WMI. Para finalizar procesos remotos, primero necesitamos averiguar qué proceso queremos finalizar. Podemos enumerar todos los procesos en ejecución en una computadora remota mirando la clase Win32_Process.

PS> Get-CimInstance -ClassName CIM_Process -ComputerName DC

ProcessId Name                                      HandleCount WorkingSetSize VirtualSize   PSComputerName
--------- ----                                      ----------- -------------- -----------   --------------
0         System Idle Process                       0           4096           65536         DC
4         System                                    631         212992         3465216       DC
232       smss.exe                                  52          823296         4325376       DC
328       csrss.exe                                 258   om      3346432        49483776      DC
392       csrss.exe                                 87          2789376        44507136      DC
400       wininit.exe                               80          3072000        2199065096192 DC
428       winlogon.exe                              119         4431872        2199079510016 DC

Una vez que hayas determinado qué proceso finalizar, puedes pasar el nombre al método Terminate() en la clase Win32_Process. Para hacer eso, necesitas capturar una instancia del proceso que deseas finalizar.

Observa a continuación que estoy usando el parámetro Filter para asegurarme de recibir solo el proceso ccmexec.exe. ¡Esto es importante!

Una vez que hayas capturado la instancia, puedes invocar el método Terminate() para finalizar el proceso usando el comando Invoke-CimMethod como se muestra a continuación.

PS> $instance = Get-CimInstance -ClassName CIM_Process -ComputerName DC -Filter 'Name = "ccmexec.exe"'
PS> $instance

ProcessId Name        HandleCount WorkingSetSize VirtualSize PSComputerName
--------- ----        ----------- -------------- ----------- --------------
3528      CcmExec.exe 878         34246656       158261248   DC


PS> Invoke-CimMethod -InputObject $instance -MethodName Terminate

ReturnValue PSComputerName
----------- --------------
          0 DC

Resumen

Si deseas aprender más sobre el uso de WMI en PowerShell y especialmente el uso del cmdlet de WMI de PowerShell Get-WmiObject que no se cubrió aquí, te animo a consultar Get-WmiObject: Consultar WMI en Computadoras Locales y Remotas donde profundizo en WMI y uso el cmdlet Get-WmiObject.

Para obtener un desglose completo de todos los cmdlets de CIM y cómo funcionan en PowerShell, consulte el artículo Introducción a los cmdlets de CIM en Technet. Allí verá todos los diversos cmdlets de CIM y cómo podrían ser utilizados en sus scripts.

Source:
https://adamtheautomator.com/powershell-wmi/