Práce s WMI (Windows Management Instrumentation) je v PowerShellu vynikající již od verze 1. Pro mne osobně byl pádným argumentem pro přechod na PowerShell cmdlet Get-WmiObject. S jeho pomocí jsem mohl (a samozřejmě stále mohu) přistupovat ke svému ConfigMgr serveru. Get-WmiObject (a jeho alias gwmi) vám zpřístupňuje WMI velice jednoduchým způsobem. Ve spolupráci s Get-Member se často obejdete bez externí nápovědy.

Malá rozcvička pro ty, kteří Get-WmiObject nepoužívají:

PS C:\> Get-WmiObject -Class Win32_B* -List

NameSpace: ROOT\cimv2

Name                    Methods              Properties
----                    -------              ----------
Win32_BaseBoard         {IsCompatible}       {Caption, ConfigOptions, CreationClassName, Depth...}
Win32_BIOS              {}                   {BiosCharacteristics, BIOSVersion, BuildNumber, Caption...}
Win32_BaseService       {StartService, St... {AcceptPause, AcceptStop, Caption, CreationClassName...}
Win32_Battery           {SetPowerState, R... {Availability, BatteryRechargeTime, BatteryStatus, Caption...}
Win32_Bus               {SetPowerState, R... {Availability, BusNum, BusType, Caption...}
Win32_BootConfiguration {}                   {BootDirectory, Caption, ConfigurationPath, Description...}
Win32_Binary            {}                   {Caption, Data, Description, Name...}
Win32_BindImageAction   {Invoke}             {ActionID, Caption, Description, Direction...}

Pomocí parametru List můžeme zjistit všechny třídy začínající na Win32_B. Ve výpisu nás zajímá třída Win32_BIOS a proto si zobrazíme její obsah:

PS C:\> Get-WmiObject -Class Win32_BIOS

SMBIOSBIOSVersion : A37
Manufacturer      : Dell Inc.
Name              : Phoenix ROM BIOS PLUS Version 1.10 A37
SerialNumber      : 20XXXX0
Version           : DELL – 1234abcd

Nezapomeňte, že některé objekty nezobrazují standardně všechny své vlastnosti. Proto i u předchozího příkladu, zkuste použít

PS C:\> Get-WmiObject -Class Win32_BIOS | Format-List *

V PowerShell v2 byly uvedeny některé nové cmdlety pro práci s WMI a ve verzi 3 jsme se dočkali další velké změny.

WMI vs. CIM

Aniž bych chtěl zabíhat do přílišných detailů, bylo by dobré zmínit, že WMI je Microsoft implementace standardu CIM (Common Information Model). V současnosti tedy máme v PowerShellu dvě možnosti přístupu do WMI:

Poznámka: Budu zde tyto dvě možnosti nazývat jako „WMI cmdlety“ a „CIM cmdlety“. Vždy v uvozovkách – nejedná se o žádný zavedený název, pouze chci odlišit „starý“ a „nový“ přístup.

„WMI cmdlety“ – Některé z nich jsou dostupné již od v1. Stále existují i ve verzi 3, ale vypadá to, že Microsoft je již dále nebude rozvíjet. Pro účely zpětné kompatibility, ale samozřejmě zůstávají (otázkou je, jak to bude v další verzi PowerShellu). Nevýhodou těchto cmdletů je, že potřebují pro své fungování RPC. Hodně problémů při práci s těmito cmdlety je způsobeno právě špatným nastavením RPC. Jste pak nuceni strávit svůj čas odhalováním potenciálního problému.

Seznam „WMI cmdletů“ v PowerShellu v3:

PS C:\> Get-Command -CommandType cmdlet -Name *wmi*

CommandType Name              ModuleName
----------- ----              ----------
Cmdlet      Get-WmiObject     Microsoft.PowerShell.Management
Cmdlet      Invoke-WmiMethod  Microsoft.PowerShell.Management
Cmdlet      Register-WmiEvent Microsoft.PowerShell.Management
Cmdlet      Remove-WmiObject  Microsoft.PowerShell.Management
Cmdlet      Set-WmiInstance   Microsoft.PowerShell.Management

„CIM cmdlety“ – S uvedením Windows Serveru 2012 jako cloud OS Microsoft přidal tyto cmdlety. Jejich výhodou je, že jsou schopny pracovat oproti WMI, ale i oproti jiným systémům využívajícím implementaci CIM standardu. Výsledkem je poté možnost spravovat například operační systémy Linux (pokud vás zajímá tato možnost více, zkuste si najít odkazy na NanoWBEM).

Další výhodou „CIM cmdletů“ je to, že komunikují pomocí protokolu WSMan. Tento protokol využívá pro přenos dat mezi počítači protokol http (nebo HTTPS – v závislosti na vašem nastavení) a je tedy velice jednoduché jej nastavovat. WSMan se používá již od PowerShellu v2 (kde byl použit poprvé pro vzdálený přístup). Vzhledem k tomu, že WSMan je na serverech (od verze 2008 R2) standardně zapnut a nakonfigurován, je použití „CIM cmdletů“ transparentní.

Seznam „CIM cmdletů“ v PowerShellu v3:

PS C:\> Get-Command -CommandType cmdlet -Name *cim*

CommandType Name                         ModuleName
----------- ----                         ----------
Cmdlet      Get-CimAssociatedInstance    CimCmdlets
Cmdlet      Get-CimClass                 CimCmdlets
Cmdlet      Get-CimInstance              CimCmdlets
Cmdlet      Get-CimSession               CimCmdlets
Cmdlet      Invoke-CimMethod             CimCmdlets
Cmdlet      New-CimInstance              CimCmdlets
Cmdlet      New-CimSession               CimCmdlets
Cmdlet      New-CimSessionOption         CimCmdlets
Cmdlet      Register-CimIndicationEvent  CimCmdlets
Cmdlet      Remove-CimInstance           CimCmdlets
Cmdlet      Remove-CimSession            CimCmdlets
Cmdlet      Set-CimInstance              CimCmdlets

Pokud se podíváte na oba výpisy, najdete některé z cmdletů v obou z nich (i když s mírně odlišnými jmény):

  • Get-WmiObject -> Get-CimInstance
  • Invoke-WmiMethod -> Invoke-CimMethod
  • Register-WmiEvent -> Register-CimIndicationEvent
  • Remove-WmiObject -> Remove-CimInstance
  • Set-WmiInstance -> Set-CimInstance

Pokud máte správně nastaveny protokoly RPC i WSMan je jedno, který z příkazů použijete. Osobně doporučuji začít si zvykat na „CIM cmdlety“. Ještě jednou připomínám, že na Windows OS je jedno (z hlediska vrácených dat), který z cmdletů použijete.

Poznámka: Pro mne osobně je „těžké“ si na nové zvyknout. Vše je ale spíše způsobeno mými prsty, které automaticky stále píší gwmi místo hlavou chtěného gcim (alias pro Get-CimInstance).

Pojďme si porovnat výstupy Get-WmiObject a Get-CimInstance.

PS C:\> Get-CimInstance win32_bios

SMBIOSBIOSVersion : A06
Manufacturer      : Dell Inc.
Name              : Phoenix ROM BIOS PLUS Version 1.10 A06
SerialNumber      : 1234567
Version           : DELL - 12345abc

PS C:\> Get-WmiObject win32_bios

SMBIOSBIOSVersion : A06
Manufacturer      : Dell Inc.
Name              : Phoenix ROM BIOS PLUS Version 1.10 A06
SerialNumber      : 1234567
Version           : DELL – 12345abc

Vidíte, že výsledek je naprosto stejný. Můžeme si potvrdit i pomocí Get-Member, že oba cmdlety vrací stejnou třídu z WMI:

PS C:\> Get-WmiObject win32_bios | Get-Member

    TypeName: System.Management.ManagementObject#root\cimv2\Win32_BIOS

PS C:\> Get-CimInstance win32_bios | Get_Member

    TypeName: Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_BIOS

Jak bylo řečeno – vrácená třída je stejná (namaspace root/cimv2), pouze typ objektu se liší v závislosti na použité metodě. Pro nás jako „koncové uživatele“ PowerShellu je jedno, jaká metoda je použita pod povrchem.

I když to na první pohled vypadá, že oba cmdlety jsou identické, jsou zde mírné změny v jejich syntaxi. Nalezení rozdílů ponechám plně na vašem samostudiu. Pouze upozorním na zřejmě největší rozdíl. Get-CimInstance nemá (narodíl od Get-WmiObject) parametr Credential. Pokud potřebujete spustit gcim na vzdáleném počítači s jiným jménem/heslem, musíte jej použít v kombinaci s Invoke-Command, například takto:

PS C:\> Invoke-Command -ScriptBlock { Get-CimInstance -Class Win32_BIOS } -Computer $server –Cred $cred

Po chvilce používání zjistíte, že „CIM cmdlety“ jsou trošku „ukecanější“.

Pojďme si ještě ukázat rozdíl mezi Invoke-WmiMethod a Invoke-CimMethod. Nejlépe na spuštění nějakého procesu.

PS C:\> Invoke-WmiMethod -Class Win32_Process -Name Create -ArgumentList notepad.exe

__GENUS          : 2
__CLASS          : __PARAMETERS
__SUPERCLASS     :
__DYNASTY        : __PARAMETERS
__RELPATH        :
__PROPERTY_COUNT : 2
__DERIVATION     : {}
__SERVER         :
__NAMESPACE      :
__PATH           :
ProcessId        : 4336
ReturnValue      : 0

Výsledkem je spuštění notepadu. Ve výpisu vidíme, že ReturnValue je 0, tedy úspěch. Bohužel jsem před pár dny řešil problém, kdy spuštění procesu na vzdáleném počítači vracelo chybu 3. Po chvíli pátrání se ukázalo, že chyba byla v nastavení RPC. Pokud bych mohl použít PowerShell v3, měl bych práci o hodně ulehčenou:

PS C:\> Invoke-CimMethod -ClassName Win32_Process -Name Create -Arguments @{CommandLine='notepad.exe'}

ProcessId ReturnValue PSComputerName
--------- ----------- --------------
3720      0

Opět – „ukecanější“ zadání, jednodušší správa a možnost spuštění na vzdáleném počítači. Všimněte si parametru Arguments. Jeho hodnotou je hash tabulka. Výhodou je, že pokud volaná metoda (v našem případě Create) potřebuje více parametrů, můžete je zadat jednoduchým způsobem do této tabulky. V případě Invoke-WmiMethod musíte zapsat všechny parametry ve správném pořadí, což občas přináší nečekané strasti. Více například v článku od Shaye Levyho: http://blogs.microsoft.co.il/blogs/scriptfanatic/archive/2010/12/16/invoking-wmi-methods-in-powershell.aspx

Pozor: Shay ukazuje příklad na formátování disku. Nepodlehněte pokušení zkoušet jeho příklad na počítači, na kterém vám záleží! Veselý obličej

Pokud byste se chtěli o „nových CIM cmdletech“ dozvědět více, doporučuji podívat se na následující zdroje:

Pokud máte nainstalován PowerShell v3, doporučuji vám začít postupně používat „CIM cmdlety“. Vzhledem k tomu, že za nějakou dobu budou hlavní možností správy, vložený čas se vám rozhodně vrátí.

- David Moravec, MVP