Powershell seriál – dolujeme data aneb jak na WMI (část 4.)

Než začneme s dnešní dávkou informací, chtěl bych se zmínit o změně, která se udála ve světě PowerShellu od vydání posledního dílu tohoto seriálu. 27.října byl uvolněn PowerShell v2 pro platformy Windows XP a Windows Server 2003 a nyní je tedy nová verze PowerShellu dostupná pro všechny hlavní platformy od Microsoftu. PowerShell v2 můžete (a vřele vám to doporučuji) stahovat z https://support.microsoft.com/kb/968929 Vzhledem k této změně budu od tohoto dílu používat pro všechny příklady novou verzi. Zrovna u WMI se nám to bude velice hodit J

WMI (Windows Management Instrumentation) – technologie vynikající, leč – bohužel – částí administrátorů nenáviděná nebo (!) nepoznaná. Pro potřeby tohoto článku se spokojíme se zjednodušenou definicí, že WMI je technologie sloužící ke správě Windows systémů. Pokud byste se chtěli dozvědět víc, zkuste například mé oblíbené MSDN: https://msdn.microsoft.com/en-us/library/aa394582(VS.85).aspx

Pro potřeby tohoto článku budu předpokládat, že znáte základní informace o WMI a že víte, co je třída, vlastnost, WQL nebo instance.

1.1 Jak získat data z WMI

Náš hlavní kamarád pro dnešek bude gwmi – co to asi může být? Jedná se o alias - malý test, jestli si pamatujete minulý díl :)

ps1

Get-WmiObject je – dle mého názoru – základním příkazem pro práci s WMI v PowerShellu. Ve v1 byl pouze tento cmdlet. Ve v2 jsou navíc tyto cmdlety: Invoke-WmiMethod, Remove-WmiObject, Register-WmiEvent, Set-WmiInstance.

Pojďme si ukázat základní použití cmdletu Get-WmiObject. Potřebujeme například zjistit typ našeho počítače:

ps2

Jednoduché, efektivní. Pokud jste někdy pracovali s WMI ve VB Scriptu, musí vám předchozí příklad připadat jako zázrak. Ve VBS bylá práce s WMI – řekněme – trochu komplikovaná (já osobně jsem do WMI přistupoval s lehkým odporem). S PowerShellem se situace změnila. Get-WmiObject je prostě dar z nebes (možná trochu přeháním, ale vzhledem k tomu, že s WMI pracuji každý den, vím, o čem mluvím).

Při práci s WMI vás budou asi nejvíce zajímat třídy, jejichž jméno začíná na Win32. Můžeme si je vypsat tímto příkazem:

ps3

Nebudu zde vypisovat všechny vrácené třídy, zkuste si je vypsat sami. Na mém počítači jich je 476. Zajímavé jsou například (kromě již zmíněné Win32_ComputerSystem) i Win32_OperatingSystem, Win32_Product nebo Win32_QuickFixEngineering (+ dalších asi 20, které budete používat nejčastěji, ale zkuste je najít sami – každému bude vyhovovat něco jiného dle zaměření). Pojďme si ukázat ještě jeden krátký příklad a poté se podíváme na složitější konstrukce. Bude nás zajímat verze operačního systému a service pack.

ps4

1.2 Parametry cmdletu Get-WmiObject

Jeden z prvních parametrů, který určitě využijete je –computername. Již v PowerShellu v1 bylo možné je připojit na vzdálený počítač a zjistit informace z WMI. Stačilo použít právě tento parametr. Pokud si například chcete udělat inventuru instalovaný service packů na vaší síti, stačí použít následující příklad:

ps5

Daleko efektivnější než psát jména počítačů do konzole bude zřejmě čtení z textového souboru, takže náš příklad upravíme následovně:

ps6

Při čtení některé z objemnějších tříd v WMI je lepší využít některý z následujcích parametrů: Filter nebo Query. Důvody jsou dva – rychlost zpracování a objem přenášených dat (ve spojení s parametrem ComputerName). Ukážeme si tři různé přístupy k získání požadovaných informací a povíme si o jejich výhodách a nevýhodách. Úkolem bude zjistit, jestli máme na počítači nainstalován produkt PowerGUI (mimochodem vynikající, volně dostupný editor na PowerShell).

Pro zjištění instalovaných programů použijeme třídu Win32_Product. Prvním vaším nápadem bude možná útok „hrubou silou“ – gwmi Win32_Product – v záplavě ujíždějících obrazovek si poté zpětně najdete (nebo nenajdete) požadovanou informaci. Toto je samozřejmě cesta, ale pro naše potřeby ji budeme považovat za nevhodnou (i když někdy je tento styl to nejrychlejší, co v praxi máte).

Jako další by vás mohlo napadnout použít filtrování objektů z minulého dílu a použít Where-Object.

ps7

V tomto případě by se nám měl vrátit záznam pouze pro zmiňované PowerGUI. Tato metoda není špatná, ale má jednu vadu. PowerShell vznese dotaz do WMI, dostane zpět všechna data z třídy Win32_Product a poté je pomocí cmdletu Where-Object filtruje na základě našeho požadavku. Problém máme právě s oním slůvkem „všechno“. Objekty opravdu filtrujeme až na úrovni PowerShellu, což není úplně efektivní. Lepší je, pokud filtrujeme data přímo na úrovni WMI (čímž zrychlujeme provádění dotazu). Zpátky se nám pak vrátí pouze data splňující zadanou podmínku. Což v případě přístupu na vzdálený počítač snižuje zatížení sítě. Použijeme tedy parametr Filter.

ps8

Nyní jsme přenesli filtrování dovnitř WMI a zpět se nám vrací pouze data spňující podmínku uvnitř filtru. Zde již potřebujeme alespoň základní znalosti WQL (https://msdn.microsoft.com/en-us/library/aa394606(VS.85).aspx). Pokud chceme mít úplnou kontrolu nad filtrováním, můžeme použít parametr Query a příklad přepsat následujícím způsobem.

ps9

Nyní jsme použili kompletní dotaz pomocí WQL. Uvědomte si, že vše, co se nám vrací je opět objekt a proto můžeme použít například následující konstrukci:

ps10

Pokud se chcete podívat na srovnání rychlosti zmiňovaných přístupů, podívejte se například na https://powershell-cz.blogspot.com/2009/08/ziskavani-informaci-z-wmi.html

Osobně používám Get-WmiObject velmi často, a většinou používám buď první (hrubá síla) nebo poslední (Query) přístup. Při použití obou přístupů většinou ukládám vrácené objekty do proměnné, se kterou dále pracuji.

1.3 Parametr AsJob

V PowerShellu v2 se objevila (mimojiné) možnost spouštět cmdlety na pozadí. Toto je obrovská výhoda při spouštění příkazů, které trvají dlouhou dobu. Můžete si běh příkazu přepnout do pozadí a dále pracovat v konzoli bez jejího blokování běžícím příkazem. Pokud budeme chtít poslední příkaz vylepšit, použijeme tedy

 ps11

Dotaz do WMI se přesune na pozadí a okamžitě se objeví příkazový řádek. Můžete pracovat dále a za chvíli zjistit stav běžícího dotazu pomocí cmdletu Get-Job.

 ps12

Je vidět, že job nám ještě stále běží. Pokud skončí, uvidíte následující výsledek:

 psXC

State je nyní Completed a proto si můžeme zobrazit výsledek

ps13

Receive-Job přináší jedno nebezpečí. V případě, že jej použijete, jak bylo naznačeno, data obdržíte zpět, ale pokud si je neuložíte, znovu už je nezískáte. Zkuste zavolat příkaz znovu a uvidíte. Máte dvě možnosti: 1) uložit si výstup cmdletu Receive-Job do proměnné nebo 2) zavolat Receive-Job s parametrem –Keep.

Závěrem jedna malá odbočka k testovanému PowerGUI. Pokud se chcete podívat, jak přistupovat do WMI přes PowerGUI, stáhněte si tento produkt z www.powergui.org a prozkoumejte větev WMI Browser. Vynikajícím zdrojem pro průzkum WMI z PowerShellu je také WMI Explorer on /\/\o\/\/a.

Dnes jsme se lehce podívali na jednu novinku v PowerShellu v2 – joby. Vzhledem k tomu, že verze 2 je nyní standard budu ji v dalších dílech využívat vice. Po plánovaném posledním díle se zaměříme na novinky, které nám – administrátorům – výrazně ulehčují nebo zrychllují práci.

- David Moravec

Další díly seriálu:
Seriál: Windows Powershell – PS pro programátory (část 6.)
Seriál: Windows Powershell - souborový systém a registry (část 5.)
Seriál: Windows Powershell – roury a aliasy (část 3.)
Seriál: Windows Powershell – objekty a roury (část 2.)
Seriál: Windows Powershell – úvod (část 1.)