A PowerShell programozási nyelv

Típusok, típuskonstrukciók

Típusszerkezet

A Windows PowerShell-ben csakis osztályokkal dolgozhatunk, minden osztály közös őse a System.Object. A C# programozási nyelvvel ellentétben a számok ábrázolásához is a System.Number osztály valamely alosztályát használjuk, nem pedig egy primitív típust.

Elemi típusok

Számok

A Windows PowerShell támogatja az összes .NET szám típust, ahogy ez az alábbi táblázatban látható:

.NET típusnév Rövid típusnév Példa
System.Int32 [int] 42
System.Int64 [long] 20000000000
System.Double [double] 4.2
System.Decimal [decimal] 42d
System.Byte [byte] 2

Képesek vagyunk egy változó típusát lekérdezni a getType() metódus segítségével. Példák:

PS C:\Users\Administrator> $myval = 10.432 PS C:\Users\Administrator> $myval.gettype()

IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Double System.ValueType

PS C:\Users\Administrator> [byte] $myval = 10 PS C:\Users\Administrator> $myval.gettype()

IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Byte System.ValueType

Stringek

Általában a PowerShell képes kikövetkeztetni egy változó típusát, mint például az alábbi string esetén:

PS C:\Users\Administrator> write-output -inputobject hello

hello

Azonban ha a write-output-nak több mint egy, space-ekkel elválasztott szót adunk meg, a PowerShell az első utáni szavakat argumentumként kezeli:

PS C:\Users\Administrator> write-output -inputobject hello world

Write-Output : A parameter cannot be found that matches parameter name 'world'. At line:1 char:13 + write-output <<<< -inputobject hello world

Ezt a problémát idézőjelek használatával oldhatjuk meg:

PS C:\Users\Administrator> write-output -inputobject "hello world"

hello world

A " " egyik előnye, hogy a " "-el hivatkozott változók megőrzik értéküket:

PS C:\Users\Administrator> $color = "kék" PS C:\Users\Administrator> write-output -inputobject " A kedvenc színem a $color"

A kedvenc színem a kék.

Ha mondjuk a string tartalmaz $ jelet, akkor az a probléma áll elő, hogy a PowerShell változóként próbálja értelmezni és megpróbálja kiírni az így kapott változó értékét:

PS C:\Users\Administrator> write-output -inputobject "Ennek a terméknek az ára: $42"

Ennek a terméknek az ára:

Ilyenkor kell alkalmaznunk az aposztrófot, melyet felfoghatunk úgy, hogy minden ami aposztrófok között van, az szó szerint értendő:

PS C:\Users\Administrator> write-output -inputobject 'Ennek a terméknek az ára: $42'

Ennek a terméknek az ára: $42

Bool

A Windows PowerShell bool típusának működése elég sokszínű, melyet legjobban az alábbi példákon keresztül lehet bemutatni. A példák során felhasználjuk az alábbi kódot:

PS C:\Users\Administrator> function test ($VALUE) { >> if ($VALUE) { >> Write-Host -ForegroundColor GREEN "TRUE" >> } else { >> Write-Host -ForegroundColor RED "FALSE" >> } >> }

PS C:\Users\Administrator> test $TRUE TRUE PS C:\Users\Administrator> test $FALSE FALSE PS C:\Users\Administrator> test TRUE TRUE PS C:\Users\Administrator> test FALSE TRUE

A $TRUE és $FALSE érthető módon veszi fel az igaz és hamis értékekeket, a test TRUE esetén a PowerShell a TRUE-t stringként kezeli, és ez esetben ha a string hossza 0, akkor hamis értéket rendel hozzá, egyébként igazat. Mivel a FALSE hossza 5, ezért igaz érték tartozik hozzá.

A PowerShell rendelkezik két beépített változóval is ($true, $false), hogy ezek reprezentálják az igaz és hamis logikai értéket.

A bool változókat használhatjuk annak ellenőrzésére is, hogy deklaráltunk-e egy változót vagy sem.

PS C:\Users\Administrator> $x=42 PS C:\Users\Administrator> test $x

PS C:\Users\Administrator> test $x TRUE PS C:\Users\Administrator> $x=0 PS C:\Users\Administrator> test $x FALSE

Amennyiben viszont a példában szereplő $x-nek 0 értéket adunk, a 0 kiértékelése során hamis értéket fogunk visszakapni.

Ezen a problémán úgy segíthetünk, ha a PowerShell-nek kiadjuk a Set-PSDebug -strict utasítást.

PS C:\Users\Administrator> Set-PSDebug -strict PS C:\Users\Administrator> $SomethingWhichWasNotDeclared

The variable $SomethingWhichWasNotDeclared cannot be retrieved because it has not been set yet. At line:1 char:29 + $SomethingWhichWasNotDeclared <<<<

A bool érték ezen felhasználási módja mellett a PowerShell készítői az overhead csökkentése miatt döntöttek.

Típuskonstrukciók

Tömb típus

A Windows PowerShell-ben nincs array literál, cast-olással vagy operátorral történő konstrukció segítségével hozhatunk létre tömböket.

Tömb létrehozásának legegyszerűbb módja a vessző ( , ) operátor segítségével az alábbi módon történik: (hasonlít a LISP cons operátorára)

PS C:\Users\Administrator> $a = , 1 # egy elemet tartalmazó tömb PS C:\Users\Administrator> $a = 1,2 # két elemet tartalmazó tömb PS C:\Users\Administrator> $a = 1,2,42 # három elemet tartalmazó tömb PS C:\Users\Administrator> $a = (1,2),(42,42) # egy tömb, melynek két eleme két-két elemet tartalmazó tömb PS C:\Users\Administrator> $a += (19,87,04,04) # az előző tömbhöz hozzá- adunk mégegy négy elemű tömböt

Egy tömb elmeinek elérése a szokásos szintaxissal történik:

PS C:\Users\Administrator> $a[0] 1 2

Aki ismeri már a PowerShell szintaxisát, az joggal kérdezheti, hogyha a @() nem tömb literál, akkor mégis micsoda. Ennek a kérdésnek a megválaszolásához először a tömbök és a típuskényszerítés viszonyát kell tisztázni.

PowerShell-ben lehetőségünk van skalár objektumokat tömb objektumokká cast-olni:

PS C:\Users\Administrator> $a = [array] 42 PS C:\Users\Administrator> $a[0]

PS C:\Users\Administrator> 42

Azonban ilyen módon nem tudunk többdimenziós tömböket létrehozni:

PS C:\Users\Administrator> $a = [array] [array] 42

Az első típuskényszerítés után a másodiknak már sok értelme nincs, újra array típusra cast-olunk, de ettől nem lesz 2 dimenziós tömbünk.

Két dimenziós tömböt a vessző operátor segítségével így hozhatunk létre:

PS C:\Users\Administrator> $a = ,,42 PS C:\Users\Administrator> $a[0][0]

PS C:\Users\Administrator> 42

Többdimenziós tömbök esetén nem kell az egyes dimenzióknak azonos hosszúságúnak lennie.

PS C:\Users\Administrator> $a = (1,2,3),(("alma","korte"),"repa"),'z' PS C:\Users\Administrator> $a[1][0][0] alma

A @( ... ) pedig nem más mint a [array] $( ... ) rövidebb alakja.

Felvetődik a kérdés, hogy a PowerShell készítői miért döntöttek ilyen megoldások mellett. Erre a válasz az, hogy a vessző operátor használatával megpróbálták konzisztenssé tenni a tömbkonstrukciós műveletet a parancsok argumentumainak szintaxisával:

PS C:\Users\Administrator> function f([array] $x, [array] $y, [array] $z) { ... } PS C:\Users\Administrator> f a,b,c z l,m

A @ jel használata akkor javasolt, ha pipeline-t használunk értékadás jobb oldalán, ilyenkor a pipeline értékét egy stream-ből veszi ki, emiatt pedig nem tudjuk megmondani, hogy collection-t kapunk-e majd vagy sem. Ha @ jelet használunk, akkor ezzel nem kell törődnünk, mindenképpen egy tömböt kapunk majd.

PS C:\Users\Administrator> $result = @( ... pipeline ... ) # biztosan array

Típusos tömböket is létrehozhatunk, ilyenkor a tömb elemei csak az adott típusnak megfelelőek lehetnek, azonban ha új elemmel bővítjük a tömböt, annak már bármi lehet a típusa.

PS C:\Users\Administrator> $a = New-Object int[] 3 PS C:\Users\Administrator> $a += "csirke" PS C:\Users\Administrator> $a 0 0 0 csirke PS C:\Users\Administrator> $a[0] = "csirke" Array assignment to [0] failed: Cannot convert value "csirke" to type "System.Int32". Error: "Nem megfelelő a bemeneti karakterlánc formátuma.". At line:1 char:4 + $a[ <<<< 0] = "csirke" + CategoryInfo : InvalidOperation: (csirke:String) [], RuntimeException + FullyQualifiedErrorId : ArrayAssignmentFailed

Típusos tömböt létrehozhaunk másképp is:

PS C:\Users\Administrator> $a = New-Object collections.generic.list[int]

Ilyenkor .NET-es tömböt kapunk, melyet csak az Add művelettel enged bővíteni, így biztos hogy a tömb minden eleme azonos típusú lesz.

Asszociatív tömbök

A PowerShell 2.0 nagyon támogatja már a név-érték párokból álló tömbök (hashtable, dictionary) használatát, ezért többféle módot is definiál létrehozásukhoz.

PS C:\Users\Administrator> $hash = @{ Color="red"; Taste="sweet"; Shape="round"; Name="apple"} PS C:\Users\Administrator> $hash.Name apple
PS C:\Users\Administrator> $hash_string = @" >> Color = red >> Taste = sweet >> Shape = round >> Name = apple >> "@ >> PS C:\Users\Administrator> $hash = ConvertFrom-StringData $hash_string

Asszociatív tömbben egy kulcs csak egyszer szerepelhet, az elemek lekérdezése. módosítása pedig kézenfekvő.

PS C:\Users\Administrator> $hash.Name = "Apple1" PS C:\Users\Administrator> $hash.Name = "Apple1" PS C:\Users\Administrator> $hash["Name"] = "Apple2" PS C:\Users\Administrator> $hash.set_Item("Name","Apple3") PS C:\Users\Administrator> $hash.Name Apple3

Asszociatív tömb elemeinek is korlátozhatjuk a lehetséges típusát.

PS C:\Users\Administrator> $hash = New-Object "collections.generic.dictionary[string,string]"

Dátum

A nyelv által megoldható feladatok nagy részében szükség van a dátumok, időszakok megfelelő kezelésére. Ezért fontos típusává vállik a nyelvnek a [datetime]. Dátum, idő típusú változókat nagyon sokféle módon tudunk létrehozni:

PS C:\Users\Administrator> $date = [datetime] "2011. june 7." PS C:\Users\Administrator> $date = [datetime]::Parse("2011. june 7.") PS C:\Users\Administrator> $date 2011. június 7. 0:00:00 PS C:\Users\Administrator> $date = Get-Date PS C:\Users\Administrator> $date 2011. június 7. 13:55:22

Nagyon sok lehetőség van a dátumok, időpontok manipulálására, módosítására.

Amit fontos megjegyezni, hogy PowerShellben a különböző dátumok ún. ticks-ekben kerülnek tárolásra, ami az időszámításunk óta (nem 1601.01.01. 00:00 óta!) eltelt idő 100 ns-okban.

Típuskonverziók

A PowerShell dinamikusan tipizált nyelv. Ez azt jelenti, hogy nem kell deklaráláskor meghatározni egy változó adattípusát, és az adattípusok automatikusan konvertálódnak, ahogy az a script futása során szükséges. Ha egy változót olyan helyen használunk, ahol a típusa nem megfelelő, a PowerShell automatikusan megpróbálja a megfelelő típusra konvertálni. Ennek egyik oka, hogy a PowerShell a .NET framework-ön kívül Windows Management Instrumenattion (WMI), Component Object Model (COM), ActiveX Data Objects (ADO), Active Directory Service Interfaces (ADSI), Extensible Markup Language (XML) és egyéb objektumokkal is tartja a kapcsolatot.

Windows PowerShell Extended Type System (ETS)

A PowerShell megpróbál egy közös abszrakciós réteget biztosítani a felhasználó számára, amely lehetővé teszi az objektumok közötti együttműködést függetlenül azok típusától. Ezt a réteget PSObject-nek nevezzük, amely egy közös osztály minden PowerShell objektumhoz történő hozzáféréshez.

Az objektumok típusának megállapításához, dinamikus bővítéséhez a PowerShell az Extended Type System (ETS) rendszert használja. A PowerShell először megpróbálja a beépített konverziós szabályai szerint konvertálni az objektumot, majd ha ez nem sikerül, akkor a custom converter-ekkel próbálja meg a konverziót. Custom converter-eket úgy írhatunk, hogy leszármaztatunk a PSTypeConverter osztályból és megvalósítjuk a megfelelő metódusokat.

Amennyiben az ETS-nek nem sikerül végrehajtania egy konverziót, PSInvalidCastException kivételt dob.

Types.ps1xml

A Types.ps1xml fájl tartalmazza a PowerShell által használt alaptípusok tulajdonságait, ennek szerkesztésével új metódusokat és property-ket lehet hozzájuk adni. A fájl megtalálható a Windows PowerShell telepítési könyvtárában. A szerkesztés előtt mindenképpen készítsünk egy biztonsági másolatot a fájlról, mert módosításával működésképtelenné tehetjük a PowerShellt. Módosítása emiatt ellenjavalt, viszont a szerkezetét mintául véve létrehozhatunk saját, új típusokat tartalmazó ps1xml fájlokat. Amennyiben modosítanánk vagy új ps1xml fájlt hoznánk létre, ki kell adnunk az Update-TypeData %path%\newFile.ps1xml utasítást.

Add-Member

Egy objektum átalakításának további módja az Add-Member cmdlet használata.

Cast

Természetesen lehetőségünk van explicit típuskényszerítésre is (cast), ennek a szintaxisa: [típus] $változó

PS C:\Users\Administrator> $a = [String] 42

A fenti példában a 42 típusát - mely int32 lett volna - típuskényszerítettük stringre. A konverzió sikerességéről az ETS gondoskodik.

Változók, konstansok

A változók nevei elé $ jelet kell tenni. A PowerShell nem case sensitive. A név betűket, számokat és aláhúzás karaktereket (_) tartalmazhat. Tartalmazhat space-eket is, ekkor kapcsoszárójelek közé tenni a váltóznevet, például a ${Variable with spaces} érvényes változó. Ugyan nincs konvenció a váltózók elnevezésével kapcsolatosan a PowerShell-ben, de érdemes olyan neveket használni, melyek tükrözik a változó jelentését és láthatóságát.

Beépített változók

Amikor elindítunk egy PowerShell munkamenetet, jópár változót automatikusan inicializálunk. Ezeket az alábbi módon kérhetjük le:

PS C:\Users\Administrator> set-location variable: PS C:\Users\Administrator> get-childitem

Ezeket a változókat 2 nagy csoportba sorolhatjuk. Az első csoportba azok a változók tartoznak, melyek az aktuális munkamenetre vonatkozó beállításokat és információkat tartalmazzák. Ezek közül a legfontosabbak az alábbi változók:

A másik csoportba azok a változók tartoznak, melyek a PowerShell működését határozzák meg.

Változók láthatósága

A PowerShell-ben 4 láthatósági szintet különböztetünk meg: lokális, private (zárt hatókör), script, globális.

Amennyiben egy változó nem található meg egy adott hatókörben, a PowerShell a szülő hatókörben próbálja meg megkeresni, ezt pedig egészen addig ismételve, amíg meg nem találja a változót vagy el nem jut a legkülső hatókörig, amiben ha nem találja meg a változót, akkor hibaüzenetet ad.

PS C:\Users\Administrator> function f { "X = $x" } PS C:\Users\Administrator> f PS C:\Users\Administrator> X = PS C:\Users\Administrator> $x = "test" PS C:\Users\Administrator> f PS C:\Users\Administrator> X = test

Változó láthatóságát a "set-variable valtozónév -scope láthatóság" szintaxissal változtathatjuk meg.

Konstansok

A PowerShellben van lehetőségünk változókat írásvédetté és konstanssá tenni. A különbség ezek között az, hogy konstans változót nem tudunk törölni, míg írásvédettet igen. Ezek szintaxisa:

"set-variable változónév -option readonly" és "set-variable változónév változóértéke -option constant"

Kifejezések, operátorok

A függvényeket a function kulcsszóval vezetjük be, a paraméterlistát nem kötelező kiírni.

PS C:\Users\Administrator> function sayHello { "Hello World" } PS C:\Users\Administrator> sayHello Hello World

Visszatérés függvényekből

Alapesetben egy függvényből akkor tér vissza a PowerShell, ha elérte a függvény végét. Egy függvényből bármikor visszatérhetünk a return utasítás segítségével.

function sayHi { if ($name -ne "Andrew") { return } "Hello Andrew!" }

A return utasításnak megadhatunk visszatérési értéket is:

function sayHi { if ($name -ne "Andrew") { return "Sorry, I'm not allowed to talk to strangers." } "Hello Andrew!" }

Függvények manipulációja

A PowerShell a függvényeit a function névtérben (namespace) adminisztrálja, melyet map-el egy virtuális "function:" nevű meghajtóra. Ezáltal a függvények adminisztrációja és manipulációja hasonlóképpen végezhető, mint amikor a fájlrendszerrel dolgozunk.

PS C:\Users\Administrator> dir function:/multiply IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Byte System.ValueType

Amennyiben nincs szükségünk egy függvényre, azt eltávolíthatjuk az rm utasítás segítségével, hasonlóképpen, mintha egy fájlt távolítanánk el.

PS C:\Users\Administrator> rm function:/multiply

Függvények mentése fájlokba / betöltése fájlokból

Elég kényelmetlen lenne, ha minden munkamenet során szükséges lenne minden egyes korábban megírt függvényeinket begépelnünk, ezért a függvényeinket lementhetjük .ps1 kiterjesztésű fájlokba. Függvényeket egy fájlból az alábbi módon tölthetünk be:

PS C:\Users\Administrator> . ./myfunction.ps1

Betöltés után ismét elérhetjük a függvényt, ha bizonyos korábban megírt függvényeket szeretnénk, hogy a PowerShell automatikusan betöltsön minden munkamenet során, a fenti parancsot a profile.ps1 fájlba kell beírnunk.

Értékadó operátorok

Operátor Hatás
=
értékadás
+=
szokásos +=
-=
szokásos -=
*=
szokásos *=
/=
szokásos /=
%=
a jobboldallal vett osztási maradékot adja értékül a baloldalnak
$x++
$x = $x + 1
$x--
$x = $x - 1

Természetesen használható a ++$x és --$y, melyek működése megegyezik a C++-ban megszokott viselkedéssel.

Logikai operátorok

Operátor
Hatás
-and
logikai és
-or
logikai vagy
-not
logikai nem
-xor
logikai kizáró vagy
!
megegyezik a -not operátorral

Bit operátorok

Operátor
Hatás
-band
bináris és
-bor
bináris vagy
-bxor
bináris kizáró vagy
-bnot
bináris nem

Összehasonlító operátorok

Operátor
Hatás
-eq
egyenlőség vizsgálat (Equals)
-ne
nem egyenlő (Not Equal)
-gt

nagyobb (Greater Than)

-ge

nagyobb egyenlő (Greater Than or Equal To)

-lt

kisebb (Less Than)

-le

kisebb egyenlő (Less Than or Equal To)

Az & operátor

Talán a legkevésbé ismert operátor a Windows PowerShellben az & operátor, annak ellenére, hogy nagyon hasznos. Egyszerűen fogalmazva, az & operátor segítségével tetszőleges stringet próbálhatunk meg parancsként értelmezni.

Vegyük az alábbi példát:

PS C:\Users\Administrator> $myCommand="get-childitem"

Ekkor ha egyszerűen csak hivatkozunk a változóra, akkor megjelenítjük az értékét:

PS C:\Users\Administrator> $myCommand="get-childitem" get-childitem

Amennyiben viszont alkalmazzuk a & operátort:

PS C:\Users\Administrator> &$mycommand Directory: Microsoft.PowerShell.Core\FileSystem::C:\Users\Administrator Mode LastWriteTime Length Name ---- ------------- ------ ---- d-r-- 11/7/2008 4:26 PM Contacts d-r-- 11/7/2008 4:26 PM Desktop d-r-- 11/7/2008 4:26 PM Documents d-r-- 11/7/2008 4:26 PM Downloads