Jedan je od uobičajenih načina za rješavanje složenih problema u različitim programskim jezicima (a ni PowerShell skripte tu nisu nikakav izuzetak) podjela problema u veći broj jednostavnijih dijelova koji se nakon toga mogu implementirati u obliku funkcija. Upravo zbog činjenice da većina programskih jezika podržava korištenje funkcija, u ovom tekstu ćemo se, prije svega, usredotočiti na posebnosti funkcija napisanih u PowerShellu.
Prije prvog primjera funkcije važno upozorenje: tijekom pokušaja izvođenja skripte s jednom ili više funkcija može se pojaviti poruka o greški nastaloj zbog kršenja trenutačnih sigurnosnih postavki na sustavu – nešto slično kao na slici u nastavku.
Slika 1. Primjer rješavanja sigurnosnih problema kod izvođenja skripti s funkcijama
./function.ps1 : File C:\Tmp2\function.ps1 cannot be loaded. The file C:\Tmp2\function.ps1 is not digitally signed. You
cannot run this script on the current system. For more information about running scripts and setting execution policy,
see about_Execution_Policies at https:/go.microsoft.com/fwlink/?LinkID=135170.
At line:1 char:1
+ ./function.ps1
+ ~~~~~~~~~~~~~~
+ CategoryInfo : SecurityError: (:) [], PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
U tom slučaju najjednostavniji način za rješavanje problema predstavlja izvođenje sljedeće naredbe:
Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned –force
Prijeđimo sada na primjer vrlo jednostavne funkcije koja prikazuje popis svih datoteka u zadanoj mapi. Na početku izvođenja funkcije izgovara se poruka o početku izvođenja, a na kraju izvođenja poruka o završetku. U ovom konkretnom slučaju to baš nema nekog prevelikog smisla, ali je tako dobivena mogućnost demonstracije prijenosa većeg broja parametara u funkciju: početne poruke, mape čiji se sadržaj prikazuje te na kraju završne poruke.
Osnovni oblik funkcije naveden je u nastavku i pokazuje kako se u funkciju prenosi i koristi veći broj parametara.
function Get-SoftwareInfo ($text1, $folder, $text2) {
(New-Object -com SAPI.SPVoice).Speak($text1) | Out-Null
Get-ItemProperty $folder
(New-Object -com SAPI.SPVoice).Speak($text2) | Out-Null
}
Slika 2. Primjer izvođenja osnovnog oblika funkcije
Najjednostavniji način za pozivanje funkcije uz prijenos parametara je navođenje vrijednosti parametara u redoslijedu u kojem se parametri očekuju u funkciji. U sljedećem primjeru to je prvo poruka na početku funkcije, nakon toga slijedi naziv mape te na kraju završna poruka.
Get-SoftwareInfo Executing C:\Windows\* Finished
Ako iz nekog razloga želimo navesti parametre funkcije u drugačijem redoslijedu od onog definiranog kod pripreme funkcije, onda ispred same vrijednosti parametra treba navesti i njegov naziv. Evo primjera pozivanja iste funkcije s izmijenjenim redoslijedom navođenja parametara:
Get-SoftwareInfo -folder C:\Windows\* -text1 Executing -text2 Finished
Deklariranje funkcije može se u praksi bitno zakomplicirati, kao što to pokazuje sljedeći primjer. Iako ova funkcija daje iste rezultate kao i početni primjer, sadrži brojne dodatne dijelove. Na samom početku funkcije pokazano je kako se mogu pripremiti detaljne upute o samoj funkciji da bi se drugim korisnicima olakšalo njezino korištenje. Na taj način funkcija u pogledu uputa postaje praktično ravnopravna sistemskim funkcijama.
<#
.SYNOPSIS
Pregled datoteka u zadanoj mapi
.DESCRIPTION
Prikazuje sve datoteke u zadanoj mapi uz 'govorne dodatke'
.PARAMETER folder
Mapa iz koje se prikazuju datoteke
.PARAMETER text1
Tekst koji se izgovara na startu skripte
.PARAMETER text2
Tekst koji se izgovara na kraju skripte
.PARAMETER saystart
Dozvoljava izgovor prvog testa u skripti
.EXAMPLE
Get-SoftwareInfo -folder C:\Windows\* -text1 Start -text2 Stop
.EXAMPLE
Get-SoftwareInfo -folder C:\Windows\* -text1 Start -text2 Stop -saystart
#>
function Get-SoftwareInfo {
param (
$text1 = 'Executing',
[Parameter(Mandatory=$true)]
$folder,
$text2 = 'Finished',
[switch]
$saystart
)
if ($saystart){
(New-Object -com SAPI.SPVoice).Speak($text1) | Out-Null
}
Get-ItemProperty $folder
(New-Object -com SAPI.SPVoice).Speak($text2) | Out-Null
}
U slučaju potrebe za dodatnom fleksibilnošću u pogledu korištenja parametara bolje je koristiti se alternativnim oblikom sintakse. Parametri se u ovom slučaju deklariraju u samom tijelu funkcije pomoću dodatne ključne riječi “param”. Za svaki od parametara moguće je definirati njegovu vrstu, je li vrijednost parametra obvezna ili nije, podrazumijevane vrijednosti parametra (ako korisnik nije naveo vrijednosti parametra prilikom poziva funkcije), a čak je moguće definirati poseban parametar „switch” kojim se dodatno može upravljati načinom izvođenja funkcije. U ovom primjeru to je upravljanje izgovorom početne poruke.
Slijedi prikaz nekoliko različitih načina pozivanja tako deklarirane funkcije, što uključuje i oblik koji samo prikazuje upute o korištenju funkcije.
Get-SoftwareInfo -folder C:\Windows\*
Get-SoftwareInfo -folder C:\Windows\* -text1 Start -text2 Stop
Get-SoftwareInfo -folder C:\Windows\* -text1 Start -text2 Stop -saystart
Get-SoftwareInfo -?
Get-Help -name Get-SoftwareInfo –Examples
Funkcije u različitim programskim jezicima kao rezultat svojeg izvođenja u pravilu vraćaju nekakav rezultat namijenjen korištenju u drugim dijelovima programa. Po tome ni funkcije u PowerShellu nisu izuzetak, jedino što u ovom slučaju nije potrebno navoditi nekakave posebne naredbe za vraćanje rezultata (npr. return). Cjelokupan sadržaj koji se pripremi i prikaže u funkciji tijekom njezinog izvođenja (u prethodnim primjerima to je popis datoteka u mapi) automatski se vraća u glavni dio programa gdje se može naknadno koristiti za obradu u kanalima i slično.