A fejlett függvények megadására nincs külön kulcsszó, hanem a függvény definiálásakor különböző metaadatokat kell megadni. Nézzünk erre rögtön egy éles példát! Területszámító fejlett függvényt akarok létrehozni, ami annyira okos, hogy akár téglalap, akár ellipszis területét is kiszámítja, pusztán a paraméterezés alapján kitalálja, hogy a kettő közül melyikre is gondoltam:
function adv-terület
{
[cmdletbinding(DefaultParameterSetName = "téglalap")]
param(
[Parameter(
Mandatory = $true,
Position = 0,
ParameterSetName = "téglalap",
HelpMessage = "Téglalap X oldala"
)]
[double]
[ValidateScript({$_ -ge 0})]
$x,
[Parameter(
Mandatory = $false,
Position = 1,
ParameterSetName = "téglalap"
)]
[double]
[ValidateScript({$_ -ge 0})]
$y = $x,
[Parameter(
Mandatory = $true,
Position = 0,
ParameterSetName = "ellipszis",
HelpMessage = "Ellipszis kis tengelye (R)"
)]
[double]
[ValidateScript({$_ -ge 0})]
$r,
[Parameter(
Mandatory = $false,
Position = 1,
ParameterSetName = "ellipszis"
)]
[double]
[ValidateScript({$_ -ge 0})]
$p = $r
)
if($pscmdlet.ParameterSetName -eq "téglalap"){$x*$y}
else {$r*$p*[math]::pi}
}
Az első fejlett lehetőséget a következő rész határozta meg a fenti függvénydefinícióban:
[cmdletbinding(DefaultParameterSetName = "téglalap")]
A cmdletbinding kulcsszó azt határozza meg, hogy a függvény úgy viselkedik a paraméterekkel szemben, mint az „igazi” cmdletek, azaz ha több paramétert kap, mint amennyit a függvényben definiáltunk, akkor nem kapja meg a felesleget az args változó, hanem hibajelzést kapunk. A mi esetünkben két paramétert vár a függvényem, ráadásul kétfajta két paramétert, de erről majd később. Nézzük, hogyan viselkedik kettőnél több paraméter megadásánál:
[11] PS C:\> adv-terület 1 2 3 4 5
adv-terület : A positional parameter cannot be found
that accepts argument '3'
.
At line:1 char:12
+ adv-terület <<<< 1 2 3 4 5
+
CategoryInfo : InvalidArgument:
(:) [adv-terület], ParameterBi
ndingException
+
FullyQualifiedErrorId : PositionalParameterNotFound,adv-terület
A fenti hibajelzést a 3-as szám, azaz a 3. paraméter okozta, un. „ParameterBindingException” hiba lépett fel. Ezt a hibajelzést leprogramozhattam volna én is az args változó vizsgálatával, de a metaadatok használatával maga a PowerShell környezet ezt elvégzi helyettünk.
Nézzük akkor a következő „fejlettséget”, azaz a többfajta paraméterezést! Az előzőleg kiemelt cmdletbindig részben meghatároztam egy alaphelyzet szerinti paraméterezést, amelynek neve „téglalap”. Ezt a „címkét” kell majd megjelölni az egyes ide tartozó paramétereknél. Nézzünk meg egy „fejlett” paraméter-meghatározást:
[Parameter(
Mandatory = $true,
Position = 0,
ParameterSetName = "téglalap",
HelpMessage = "Téglalap X oldala"
)]
[double]
[ValidateScript({$_ -ge 0})]
$x
Ez a kiemelés egy darab paramétert definiál nagyon részletes módon. A parameter metaadat meghatározásával megadhatjuk, hogy az adott paraméter kötelező-e (mandatory) vagy sem. Meghatároztam a paraméter pozícióját (position) és hogy melyik pereméterezéshez tartozik (ParameterSetName). Megadtam egy súgó szöveget (HelpMessage), ami magyarázatot ad a paraméter használatával kapcsolatban:
[15] PS C:\> adv-terület
cmdlet adv-terület at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
x: !?
Téglalap X oldala
x: 1
1
A fenti példában nem adtam egyetlen paramétert sem a függvényemnek, így PowerShell bekérte az alaphelyzet szerinti paraméterezés kötelező paraméterét. Itt van lehetőségünk a „!?” karakterkombinációval súgót kérni. Igazából csak kötelező paramétereknél érdekes a súgó, hiszen itt van lehetőség segítséget kérni.
Mindezek után megadtam a paraméter típusát ([double]), valamint meghatároztam egy speciális ellenőrző szkriptet ([ValidateScript()]), ami jelen esetben azt ellenőrzi, hogy a paraméter nem negatív-e. Ilyen ellenőrző lehetőségekből számos van, ezeket majd a következő fejezetben tekintem át.
A paraméterdefiníció utolsó részében a paraméter változóját adom meg és az esetleges alaphelyzet szerinti értékét. A kötelező paramétereknél ilyen alapérték megadása felesleges, mert a PowerShell mindenképpen kér paramétert.
Nézzük meg, hogyan néz ki egy másik készletbe tartozó paraméter definíciója:
[Parameter(
Mandatory = $true,
Position = 0,
ParameterSetName = "ellipszis",
HelpMessage = "Ellipszis kis tengelye (R)"
)]
[double]
[ValidateScript({$_ -ge 0})]
$r
Gyakorlatilag majdnem minden ugyanaz, mint a korábban látott X paraméternél. A különbség csak a ParameterSetName metaadatnál, a súgó szövegénél és a változó nevénél van. Azaz az R paraméter is kötelező, viszont mivel ez már egy másik paraméterezéshez tartozik, az „ellipszishez”, ami nem az alaphelyzet szerinti paraméterezés, így ha paraméter nélkül hívtam meg a függvényt, erre nem kérdez rá a futtatási környezet. Viszont, ha a P paramétert használom, ami szintén az ellipszishez tartozik, de az R paramétert nem, akkor már reklamál:
[29] PS C:\> adv-terület -p 4
cmdlet adv-terület at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
r: !?
Ellipszis kis tengelye (R)
r: 4
50,2654824574367
Nézzük magát a függvénytörzset:
if($pscmdlet.ParameterSetName -eq "téglalap"){$x*$y}
else {$r*$p*[math]::pi}
A fejlett függvények egyik fő ismérve a $pscmdlet változó használata. Ez nagyon sok mindent elárul a függvényünk futásának körülményeiről. Ilyen például az, hogy melyik paraméterezést használtuk a függvény hívásakor, amit a ParameterSetName tulajdonság ad meg. A függvényem törzsében tehát elég ezt a tulajdonságot megvizsgálnom, maga a PowerShell környezet elemezte ki a paraméterek használata alapján, hogy melyik paraméterezést használtam, nem nekem kellett ezt leprogramoznom. Eszerint a téglalap és az ellipszis területének kiszámítására más-más képletet tudok alkalmazni.
Még egy dolgot nézzünk meg így bevezetésként, kérjük le a függvényem súgóját:
[23] PS C:\> get-help adv-terület -full
adv-terület [-x] <Double> [[-y] <Double>] [-Verbose] [-Debug] [-ErrorAction <A
ctionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>
] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
adv-terület [-r] <Double> [[-p] <Double>] [-Verbose] [-Debug] [-ErrorAction <A
ctionPreference>] [-WarningAction <ActionPreference>] [-ErrorVariable <String>
] [-WarningVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>]
Bár nem írtam helpet, de már körvonalazódik valami automatikusan. Megkaptam a függvényem paraméterezésének kétfajta lehetőségét és a paramétereket. Ezt majd fokozni fogjuk ebben a fejezetben később. Látható, hogy olyan paraméterek is megjelentek, amelyeket én nem is használtam. Jobban áttekinthetőek ezek a paraméterek a következő módon:
[27] PS C:\> (Get-Command adv-terület).parameters | ft -auto
Key Value
--- -----
x System.Management.Automation.ParameterMetadata
y System.Management.Automation.ParameterMetadata
r System.Management.Automation.ParameterMetadata
p System.Management.Automation.ParameterMetadata
Verbose System.Management.Automation.ParameterMetadata
Debug System.Management.Automation.ParameterMetadata
ErrorAction System.Management.Automation.ParameterMetadata
WarningAction System.Management.Automation.ParameterMetadata
ErrorVariable System.Management.Automation.ParameterMetadata
WarningVariable System.Management.Automation.ParameterMetadata
OutVariable System.Management.Automation.ParameterMetadata
OutBuffer System.Management.Automation.ParameterMetadata
Csak az első négy paraméter, amit én hoztam létre, a többit a PowerShell rakta hozzá annak köszönhetően, hogy a paraméterezésnél használtam a [Parameter] metaadat-címkét. Ezek az automatikus paraméterek az un. „common parameters”, azaz a legtöbb cmdletnél használatos paraméterek, melyekkel a függvényünk viselkedését tudjuk szabályozni a hibákkal, figyelmeztetésekkel szemben, a kimenetet átirányíthatjuk, stb. Ezeknek a használatát már részben láttuk az „igazi” cmdleteknél, részben a fejezet későbbi példáiban előkerülnek.
Azaz megszületett az első fejlett függvényem! Láthatjuk, hogy a fejlett függvényeknek a fő előnyük az, hogy egy csomó dolgot nem kell nekünk leprogramoznunk, hanem a PowerShell által biztosított általános cmdlet-vázat tudjuk felöltöztetni a saját kódunkkal. Így nem kellett külön kezelnünk a függvénynek átadott túl sok paramétert, a paraméterek ellenőrzését, a többfajta paraméterezés használatát, a paraméterek megadásának megkövetelését és a cmdleteknél gyakori paraméterek használatát. Ennél még sokkal többet is igénybe tudunk venni a PowerShell által nyújtott szolgáltatásokból, ezeket nézzük át a következő alfejezetekben.