A PowerGUI egy olyan eszköz (most nem annak script editoráról, hanem az „igazi” PowerGUI-ról beszélek), mellyel grafikus rendszergazda eszközöket lehet építeni olyanok számára, akik nem ismerik a PowerShell nyelvezetét, és nem is éri meg ezt nekik megtanulni, mert ők csak ritkán vagy pedig csak egy szűk alkalmazási területen használnák azt. És az igazán nagyszerű ebben a szoftverben, hogy olyanok építhetik meg ezeket az eszközöket, akik nem „igazi” fejlesztők, hanem „csak” rendszergazdák, akik jól ismerik a PowerShellt. Azaz nem kell Visual Studio-t használni, nem kell fordítani, hanem közvetlenül PowerShell segítségével építhetők grafikus eszközök.
Ebben a fejezetben a PowerGUI-ban történő fejlesztés főbb elemeit ismertetem, mert ez hordoz magában jó néhány tanulságot, amely az általános PowerShell ismereteinket is mélyíti.
Elsőként nézzük át a főbb elemeit a PowerGUI felületének, melyek úgy kapcsolódnak egymáshoz, mint a LEGO építőkockák elemei és együtt adnak ki egy összetettebb funkciót. A PowerGUI ablak bal oldalán építhetjük fel egy fastruktúrában a szkriptjeinket. Ez sokkal hatékonyabb tárolási lehetőség, mint hogyha a szkriptjeinket a fájlrendszerben helyeznénk el. Persze van néhány lényeges különbség a PowerGUI-ban és a fájlrendszerben tárolt szkriptek lehetőségei között, erre majd hamarosan visszatérek.
Nézzük tehát azt, hogy hogyan tudjuk ezt a fastruktúrát kialakítani! A felvehető faelemek a következők: mappa (folder), csomópont (node) és szkript-csomópont (script node).
78 . ábra PowerGUI csomópontok
Igazából nincs nagy különbség a három típus között, bármikor átalakítható egyik a másikba. A mappa csomópontok szerep igazából a további csomóponttípusok összefogása, csoportosítása. A „sima” csomópont egy meglevő cmdletet futtat, akár paraméterezhető módon. Ezt viszonylag ritkán használjuk. Az igazi lehetőségeket a szkript-csomópont rejti. Egy ilyen csomópont mögött olyan szkriptet lehet tárolni, aminek valamilyen kimenete van:
79 . ábra Az első szkript-csomópontom
A fenti példámban a szkriptem egy egyszerű kis szövegfájl-listázó műveletet hajt végre, méghozzá olyan módon, hogy a kimeneten a fájlnév és a teljes elérési út mellett a fájl tartalmának első sora is látható legyen. Ha ezt az ablakot az OK-val lezárom, vagy később bármikor erre a csomópontra kattintok, akkor a fenti szkript lefut és az eredmény az PowerGUI ablak középső részén jelenik meg:
80 . ábra A csomóponti szkript kimenete
Ez még idáig helyettesíthető lenne nagyjából az Out-GridView kimenettel is, hiszen itt is lehetne oszlopfejléceket eltüntetni, sorba rendezni, szűrni, stb. Az igazi egyedi lehetőség, amitől ez rendszergazda-eszköz lesz, hogy a jobboldali „Actions” részben újabb szkripteket lehet definiálni, melyek az eredményrácsban kijelölt elemeken valamit végeznek:
81 . ábra Cselekvési lehetőségek
A Category segítségével elválasztó címkéket vehetünk fel. Az Action lehetőséggel egy meglevő cmdletet futtathatunk, ami megint csak nem a mi igazi terepünk. A harmadik lehetőség, a Script Action kell nekünk!
82 . ábra A szkript-tevékenység sablonja
Látható, hogy egy kis keretprogramot, sablont ad rögtön nekünk a PowerGUI, ebben láthatjuk, hogy a középső ablakrészben kiválasztott objektumok lesznek majd benne az $input változóban, és ezeken hajtódik végre rendre egy ForEach-Object ciklussal az, amit mi megírunk. Azonban vigyázzunk! A tevékenységek nem csomóponthoz-kötöttek, hanem objektumtípushoz! Azaz elég egyszer definiálni egy tevékenységet, az innentől kezdve automatikusan megjelenik minden olyan esetben, amikor bármelyik csomópontra is kattintunk, de a rácsban az adott objektumtípus jelenik meg. Ezt az típus-hozzárendelést a Display Configuration gomb megnyomásával láthatjuk, illetve állíthatjuk be:
83 . ábra A tevékenység összerendelése objektumtípussal
Konkrétan most ez nem is lesz így jó nekünk, mert az én példámban a csomóponti szkript az PSObject-et, azaz hosszú nevén System.Management.Automation.PSCustomObject-et ad a kimenetén, ami túl általános, így nagy a veszély, hogy olyan csomópontoknál is megjelenik, ahol nem is szövegfájlok szerepelnek a háttérben. Szerencsére ez az objektumtípus annyira egyedi, hogy új nevet is adhatok neki, így a csomóponti szkriptet az alábbi módon módosítom:
Get-ChildItem c:\PowerGUITeszt\*.txt | ForEach-Object {
$o = New-Object -TypeName PSObject -Property @{
filename = $_.name;
elsősor = @(Get-Content $_)[0]
fullname = $_.fullname
}
$o.PSObject.TypeNames.Clear()
$o.PSObject.TypeNames.Insert(0,'En.Sajat.Egyedi.Osztalyom')
$o
}
Látható, hogy most az $o változóban kezdem felépíteni az egyedi objektumomat, melynek a típusneveket tartalmazó tulajdonságát törlöm, majd feltöltöm egy általam kitalált egyedi tulajdonságnévvel, majd az így módosított objektumot teszem ki a kimenetre.
Legyen az első tevékenység-szkriptem az, hogy a kijelölt fájlok tartamát jelenítem meg!
84 . ábra Tevékenység-szkript és a képernyőjének beállítása
Látható, hogy most már ez a szkript az én egyedi típusomhoz van rendelve, ráadásul létrehoztam egy „Saját cselekvéseim” kategóriát is, hogy elkülönüljön ez a tevékenység „gyári” tevékenységektől. És ami fontos még, hogy a „Display results” csoportban a beágyazott nézetet kértem (Display the results in a nested view), hiszen ha nem ezt tenném, akkor nem is igazán látnék semmit, mert a tartalmat a meglevő rácsban nem tudná megjeleníteni, hiszen az teljesen más objektumtípusok megjelenítésére van kialakítva.
Nézzük, most mi lesz, ha rákattintok az elkészült „Teljes tartalom megjelenítése” menümre:
85 . ábra Tevékenység-szkript eredménye
Látható, hogy a középső ablakrészben egy újabb „réteg” képződött, ahol a tevékenység-szkript eredménye vált láthatóvá. Konkrétan én most eredetileg két fájlt is kijelöltem, és mindkettő tartalma van most az ábrán soronként. Visszalépni a korábbi rácshoz a középső rész fejlécében kialakult menüstruktúra „Szkript csomópont” részére kattintva lehet.
Nézzünk most egy „még igazibb” tevékenységszkriptet, mondjuk ez csinálja azt, hogy a kijelölt szövegfájljaim első sorának az elejére beilleszti az aktuális dátumot.
# Type in a PowerShell script here
$input | ForEach-Object {
# add your processing for each item from the grid selection
# the $_ variable represents each individual object
$sorok = Get-Content -Path $_.fullname
if($sorok[0] -match '^\d{2}/\d{2}/\d{4}\s\d{2}:\d{2}:\d{2}\s'){
$sorok[0] = $sorok[0] -replace '^\d{2}/\d{2}/\d{4}\s\d{2}:\d{2}:\d{2}\s',
"$(Get-Date) "
}
else {
$sorok[0] = $sorok[0]
=
[string] (Get-Date) + "
" + $sorok[0]
}
$sorok | Set-Content -Path $_.fullname
}
És ennek megjelenítési beállításai:
86 . ábra Kimeneti objektumokat módosító tevékenység megjelenítési beállítása
Itt már nem beágyazott kimenetet kértem, hiszen ugyanazon objektumokat módosítottam, mint amit a csomóponti szkript megjelenített, így csak annyi a feladat, hogy a meglevő nézetet kellett frissítenem.
Az „aktív rács” mellett a dinamikus csomópontok létrehozásának lehetősége a másik olyan képessége a PowerGUI-nak, ami lehetővé teszi egyszerű rendszergazda tevékenységek végrehajtására. A dinamikus csomópont olyan csomópontstruktúra, ami futásidőben jön létre. Ez ott hasznos, ahol nagyon sok objektumot kellene kezelni, például egy meghajtó teljes fájlkészletét. Ezt egy rácsban nagyin nehéz lenne megjeleníteni, viszont a fájlrendszer esetében a mappák eleve adják, hogy mappánként csoportosítjuk az objektumokat, ezt kezeléstechnikailag pedig a csomópontok automatikus (dinamikus) építésével lehet elérni.
A nehézség itt az, hogy a dinamikus csomópont az csomópont a javából, így ahhoz, hogy rá kattintva valami megjelenjen a rácsban, valami szkripttel is fel kell ruházni, azaz nem elég dinamikusan „legyártani” magukat a csomópontokat, a mögöttük található szkriptet is dinamikusan kell legenerálni.
Nézzünk egy nagyon egyszerű dinamikus csomópontot, ami csak annyit csinál, hogy legenerál 1-től 5-ig számokat, ezek lesznek a dinamikus csomópontok nevei, és az egyes csomópontok szkriptje az lesz, hogy a csomópont számának megfelelő darabszámú X-et ír ki a rácsba.
87 . ábra Az első dinamikus csomópontjaim
Ezen „csomópontgyár” szkriptjében használom a PowerGUI Local System csomagjában (PowerPack, lásd később) definiált Add-AdminConsoleDynamicNode megosztott függvényt, amivel az ilyen dinamikus csomópontokat le lehet generáltatni. Ahhoz, hogy ez a függvény látható legyen az én szkriptem számára, a More gomb megnyomása után feltáruló középső ablakrészben a PowerPack-ok közé fel kellett vennem a Local System csomagot is.
A függvényt meg lehet nézni a Shared Scripts legördülő menün keresztül, a definíciós része így néz ki:
function global:Add-AdminConsoleDynamicScriptNode {
param(
$ParentNode,
[string] $Name,
$Script,
[System.Management.Automation.PSObject[]] $ScriptParameters = $null,
[System.Management.Automation.PSObject] $AssociatedObject = $null,
[System.Management.Automation.PSObject] $IconTypeIdentifier = $null,
[switch]$PassThru
)
…
Azaz meg kell adni neki, hogy melyik csomópont alá hozza létre a dinamikus csomópontot, mi legyen a neve a dinamikus csomópontnak, mi legyen a csomópont szkriptje, ha esetleg ennek a szkriptnek lennének paraméterei, akkor ezeket a következő paraméter gyanánt adhatjuk meg. Társíthatnánk még objektumhoz a kimenetet, bár ezt a lefutó szkript kimenete is meghatározhatja, és ikont is megadhatunk.
Nézzük, ennek az egyszerű dinamikus csomópontnak mi is a kinézete:
88 . ábra Egyszintű dinamikus csomópont
Látható, hogy szépen megszülettek a dinamikus csomópontok és működik a mögöttük található dinamikusan előállított szkript is. Itt tehát egy egyszintű struktúrát hoztam létre. Egy fokkal bonyolultabb eset, ha a dinamikus csomópontoknak generálodnak újabb dinamikus csomópontjuk! Ennek megvalósítása túlmutat a könyvünk keretein, de kihívást kedvelő olvasóimat arra bíztatom, hogy próbáljanak meg ilyet létrehozni.