Parameter
Um Skripte an die Umgebung anpassen zu können, in der sie gestartet werden, müssen mitunter variable Werte wie Pfade in Skripten angepasst werden. Dafür stellt Powershell Parameter zur Verfügung, die genau wie Cmdlet-Parameter mit -Parameternamen <Argument> übergeben werden und den Inhalt von Variablen beim Aufruf festlegen können.
Parameter deklarieren
Parameter werden direkt im Kopf des Skriptes in einem Param-Block deklariert:
Param(
[string]$path, [int]$Count
)
$Count # Die Parameter definieren Variablen, die im Skript direkt aufgerufen werden
$Path
Ein Parameter ist letztlich eine Variable, die direkt im Kopf des Skriptes definiert und nach außen sichtbar gemacht wird. Achten Sie darauf, dass jeder Parameter vom nächsten Parameter mit einem Komma getrennt sein muss. Der gesamte Param-Block muss von runden Klammern umschlossen und das erste Kommando im Skript sein. Vor dem Param-Block dürfen nur noch Kommentare, aber keine Cmdlets oder Befehle stehen. Die Typen der Parameter können wie im Beispiel festgelegt werden, um sicherzustellen, dass die Benutzereingaben die korrekten Datentypen haben – notwendig ist das aber nicht. Im Skript greifen Sie auf die Parameter wie auf normale Variablen zurück.
Parameter können aber noch mehr. Mit dem sogenannten Parameter-Attribut, das dem Parameter in eckigen Klammern vorangestellt wird, kann man Vorgaben für Parameter definieren.
# Kommentare dürfen hier angegeben werden
Param(
[Parameter(Mandatory=$true,Position = 0,Helpmessage='Geben Sie einen Pfad ein')]
[string]$path,
[int]$Count
)
Das Parameter-Attribut hat Argumente, die bestimmen, wie der Parameter sich verhalten soll. Im Beispiel werden folgende Argumente verwendet:
- Mandatory: sagt Powershell, ob der Parameter ein Pflicht-Parameter sein soll.
- Position: Gibt an, dass der Parameter als Positionsparameter verwendet werden kann
- Helpmessage: Eine Beschreibung, die der Benutzer anzeigen lassen kann
Wenn der Benutzer den Pflichtparameter beim Aufruf nicht angibt, wird er von Powershell erfragt. Ist Helpmessage angegeben, kann der Benutzer sich die Hilfe durch Eingabe von !? anzeigen lassen:

Abbildung 8 - Ist Helpmessage definiert, kann der Benutzer die Beschreibung abfragen
Die Parameter-Attribute können für jeden Parameter einzeln angegeben werden. Achten Sie darauf, und dass das Schlüsselwort Parameter in eckigen Klammern steht, die einzelnen Argumente wie bei Methoden in runden Klammern übergeben werden.
Param(
[Parameter(Mandatory=$true,Position = 0,Helpmessage='Geben Sie einen Pfad ein')]
[string]$Path,
[Parameter(Mandatory)] [int]$Count
)
"Hier folgt der Scriptcode"
Get-Childitem -Path $path
In diesem Beispiel ist auch für den zweiten Parameter $Count ein Parameter-Attribut übergeben worden. Wie Sie hier sehen können, kann Mandatory auch ohne die $true-Zuweisung definiert werden. Diese Schreibweise funktioniert aber erst ab Powershell 3. 0.
Übergabe der Parameter
Um das Skript mit Parametern aufzurufen, brauchen Sie an der Konsole nur die .ps1-Datei zu starten und die Parameter wie bei einem Cmdlet mit Namen (oder als Positionsparameter) zu übergeben:
TestSkript.ps1 -Path C:\windows -Count 3
Auch die automatische Erweiterung und Intellisense werden für die Parameter unterstützt.
Parametervalidierung
Seit Powershell 2 können die übergebenen Argumente direkt beim Aufruf des Skriptes überprüft werden. Dafür stehen eine ganze Reihe von Validierungsattributen zu Verfügung.
Param(
[string]$path,
[ValidateRange(1,10)]
[int]$Count
)
ValidateRange prüft, ob das übergebene Argument sich in dem Wertebereich befindet, der in den runden Klammern angegeben ist. Gibt der Benutzer beim Aufruf für Count einen Wert an, der sich außerhalb des Zahlenbereichs von 1 bis 10 befindet, erhält er eine Fehlermeldung.
TestSkript.ps1 -Path C:\windows -Count 19
> Das Argument für den Parameter "Count" kann nicht überprüft werden. Das 19-Argument ist größer als der maximal zulässige Bereich von 10. Geben Sie ein Argument an, das kleiner oder gleich 10 ist, und führen Sie dann den Befehl erneut aus
Es gibt noch eine ganze Reihe weiterer Validierungsattribute:
|
Validierungsattribut |
Funktion |
|
AllowNull() |
Der übergebene Wert darf leer sein, es muss also kein Wert übergeben werden |
|
AllowEmptyString() |
Es darf ein leerer String übergeben werden. Ein leerer String entspricht der Übergabe von "" und ist nicht identisch mit NULL. |
|
AllowEmptyCollection() |
Erlaubt leere Arrays als Übergabewert |
|
ValidateCount(1,3) |
Wenn der Parameter Arrays als Argument übernimmt, definiert ValidateCount die erlaubte Anzahl der Elemente im Array |
|
ValidateLength(3,16) |
Prüft die Anzahl der Buchstaben in einem String |
|
ValidatePattern('<Muster>') |
Das Argument muss dem Validierungsmuster entsprechen. Mehr zu regulären Ausdrücken finden Sie im Abschnitt Reguläre |
|
ValidateRange(1,10) |
Gibt den Wertebereich an, in dem sich eine Zahl bewegen darf |
|
ValidateScript(<Scriptblock>) |
Gibt ein Prüfskript an, das $true zurückgeben muss – hiermit können beliebige Prüfungen ausgeführt werden |
|
ValidateSet('Ja','Nein') |
Das Argument muss einem der Werte aus dem Set entsprechen |
|
ValidateNotNull() |
Gegenteil von AllowNull() – ein Leerwert ist nicht erlaubt |
|
ValidateNotNullorEmpty() |
Das Argument darf keinen Leerwert und keinen Leerstring sein |
Sie können sogar mehrere Prüfungen gemeinsam auf einen Parameter anwenden. Die automatische Parameter-Validierung ist eine geniale Sache, weil Sie die Richtigkeit von Benutzereingaben direkt beim Übergeben der Argumente prüfen können und Sie außerdem selbst keinen Code mehr entwickeln müssen, um die Prüfung auszuführen.
Eine frei definierte Validierung können Sie mit ValidateScript erzeugen. Ein ValidateScript ist ein benutzerdefiniertes Powershell-Skript, das beliebige Prüfungen durchführen kann. Liefert das Validierungsskript falsch oder Nichts zurück, bricht die Skriptausführung mit einer Fehlermeldung sofort ab. Das kann z.B. zur Prüfung von Pfaden verwendet werden. Das Cmdlet Test-Path übernimmt hier die Hauptarbeit, da es einen Pfad überprüft und $true oder $false zurückgibt.
Test-Path -Path C:\Windows -PathType Container
> True
Dieses Beispiel prüft, ob der Ordner C:\Windows vorhanden ist und wenn ja, ob es sich um einen Ordner ("Container") handelt. Da beides der Fall ist, liefert Test-Path $true zurück. Um ValidateScript zu sagen, an welcher Stelle er den Parameter im Skript einfügen soll, wird wieder die anonyme Variable $_ verwendet.
Param(
[ValidateSet('Gridview','CSV','Console')]
[string]$OutPutFormat,
[ValidateScript({ Test-Path -Path $_ -PathType Container })]
$path
)
Das Validierungsskript wird als Skriptblock (also mit geschweiften Klammern) angegeben. Wenn der übergebene Pfad ein existierender Ordner ist, startet das Skript. Andernfalls wirft Powershell eine (kryptische) Fehlermeldung aus:
Das Argument für den Parameter "path" kann nicht überprüft werden. Das Validierungsskript " Test-Path -Path $_ -PathType Container " für das Argument mit dem Wert "C:\demo" hat nicht "True" zurückgegeben. Ermitteln Sie, weshalb beim Validierungsskript ein Fehler aufgetreten ist, und führen Sie den Befehl erneut aus.
Diese Fehlermeldung ist für einen Benutzer nicht wirklich aussagekräftig. Leider kann man in Powershell 5 noch keine eigene Fehlermeldung für ValidateScript übergeben. Es gibt allerdings einen Workaround:
Param(
[ValidateScript({ If ( Test-Path -Path $_ -PathType Container ){ $true } Else { Throw "Der Pfad existiert nicht" }})]
$path
)
ValidateScript kann grundsätzlich nicht daran gehindert werden, bei der Rückgabe von $false eine unverständliche Standard-Fehlermeldung zurückzugeben. Um dieses Problem zu umgehen, wird mit dem Befehl Throw ein terminierender Fehler ausgelöst, der das Skript sofort beendet. Der Text hinter Throw gibt die Meldung an, die dem Benutzer ausgegeben werden soll. Throw wird nur dann aufgerufen, wenn Test-Path $false zurückgibt. Die Fehlermeldung, die generiert wird, sieht nun so aus:
Das Argument für den Parameter "path" kann nicht überprüft werden. Der Pfad existiert nicht.
Throw wird ausführlich im Abschnitt Throw behandelt. Ab Powershell 6 müssen Sie mit diesem Workaround nicht mehr leben. Stattdessen können Sie direkt eine benutzerdefinierte Fehlermeldung angeben:
param(
[ValidateScript({ Test-Path -Path $_ },Errormessage='Der Pfad existiert nicht')]
$Path
)
Automatische Argument-Ergänzung
Ein ValidateSet erlaubt, eine Liste von Werten für einen Parameter vorzugeben. Powershell kann ab Version 3 diese Werte beim Aufruf des Skripts direkt als Vorschläge anzeigen.
Param(
[ValidateSet('KB','MB','GB')]
[string]$Einheit
}
In diesem Beispiel wird ein Parameter Einheit deklariert, der drei Werte erlaubt: MB, GB und TB. Der Benutzer muss einen dieser Werte eingeben. Wenn Sie die ISE verwenden, schlägt Powershell die Parameter direkt in einem Drop-Down Fenster vor, in der Konsole können Sie die möglichen Argumente mit dem Tabulator ergänzen oder mit dem PSReadline-Modul, das ab Version 5 bereits in Powershell integriert ist, mit der Tastenkombination <Strg-Leertaste> sogar in der Konsole anzeigen lassen.

Abbildung 9 - in der ISE wird ein ValidateSet als Dropdown-Fenster angezeigt
Um für einen Parameter eine feste Vorgabe von Werten zu definieren, kann neben einem ValidateSet auch eine Enumeration (Enum) verwendet werden. Eine Enumeration ist ein .Net-Konstrukt, das sich wie ein Array mit vordefinierten Werten verhält. Das .Net-Framework stellt davon einige zur Verfügung, z.B. System.DayOfWeek oder System.ConsoleColor. Wenn man einem Parameter als Datentyp eine Enumeration vorgibt, werden automatisch nur Werte zugelassen, die in der Enumeration vorkommen.
Param(
[System.DayOfWeek]$WeekDay
)
$WeekDay

Abbildung 10 - Dank PSReadline kann man sich auch in der Konsole alle Parameter anzeigen lassen
Wenn Sie die gültigen Werte für einen Parameter dynamisch bestimmen wollen, können Sie statt des ValidateSet auf den ArgumentCompleter zurückgreifen. ArgumentCompleter bestimmt die gültigen Werte eines Parameters zur Laufzeit über einen Scriptblock.
param(
[ArgumentCompleter({( Get-PSDrive ).Name })]
$Laufwerk
)
Übergeben Sie dafür wie bei ValidateScript einen Skriptblock als Argument an ArgumentCompleter. Sinnigerweise sollte das Skript eine Liste von Einzelwerten zurückliefern, wie z.B. ein String-Array. Im Beispiel wird mit ( Get-PSDrive ).Name die Liste aller Laufwerke abgerufen und die Eigenschaft Name aufgelöst. Mehr zum ArgumentCompleter finden sie unter http://powershell.one/powershell-internals/attributes/auto-completion
Parameter-Sets
Parameter-Sets definieren Parameter, die sich gegenseitig ausschließen oder nur in Kombination mit bestimmten Parametern verwendet werden können. Bleiben wir dazu noch einmal beim Beispiel der Ausgabe als Gridview oder CSV-File. Es macht normalerweise keinen Sinn, bei der Ausgabe mit einem Gridview einen Pfad anzugeben, bei der Ausgabe per CSV ist dieser aber Pflicht.
param(
# Ausgabe als Gridview
[Parameter(Mandatory=$true, ParameterSetName='Grid')]
[switch]$Grid,
# Ausgabe als CSV-Datei in den angegebenen Pfad
[Parameter(Mandatory=$true, ParameterSetName='CSV')]
[string]$Path
)
If ( $PSCmdlet.ParameterSetName -eq 'Grid' )
{
Get-command | Out-GridView
}
Else
{
Get-Command | Export-CSV -Path $Path
}
Im Parameter-Attribut wird für die beiden Parameter $Grid und $Path ein Parameterset-Name gesetzt. Dadurch werden zwei Parametersätze gebildet. Beim Aufruf des Skripts zeigt Powershell, sobald ein Parametersatz eindeutig erkannt ist, nur noch die Parameter an, die zum Parametersatz gehören, sowie alle Parameter, die keinem Parametersatz angehören (bei denen also im Parameter-Attribut kein Parametersatz angegeben wurde).

Abbildung 11 - Sobald Powershell einen Parameter-Satz erkennt, werden nur noch passende Parameter angezeigt
Wie man in der Abbildung sieht, zeigt Powershell den Parameter -Path nicht mehr an, sobald -Grid in der Konsole eingegeben wurde. Das spiegelt sich auch in der Hilfe wider:

Abbildung 12 - Zwei Parametersätze in der Hilfe
Man erkennt hier zwei unterschiedliche Aufrufe, einmal mit -Grid und den allgemeinen Parametern, und einmal mit -Path und den allgemeinen Parametern. Das Skript muss nun, je nach angegebenen Parametersatz, entweder Out-Gridview oder Export-CSV aufrufen. Das angegeben Parameter-Set steht im Skript in der automatischen Variablen $PSCmdlet.ParameterSetName zur Verfügung und kann dort als String ausgelesen werden.
Man kann einen Parameter auch mehreren Parametersätzen zuordnen und sogar für jedes Parameterset andere Optionen setzen. Jeder Parameter wird weiterhin nur einmal definiert, aber für jeden Parametersatz muss ein eigenes Parameter-Attribut gesetzt werden. Im folgenden Beispiel ist der Parameter CSV als Switch-Parameter definiert worden, und es wurde ein zusätzlicher Parameter XML hinzugefügt. Der Pfad muss jetzt für die beiden Parametersätze XML und CSV angegeben werden.
param(
{
# Ausgabe als Gridview
[Parameter(Mandatory=$true, ParameterSetName='Grid')]
[switch]$Grid,
[Parameter(Mandatory=$true, ParameterSetName='CSV')]
[Switch]$CSV,
[Parameter(Mandatory=$true, ParameterSetName='XML')]
[Switch]$XML,
# Ausgabe als CSV-Datei in den angegebenen Pfad
[Parameter(Mandatory=$true, ParameterSetName='CSV')]
[Parameter(Mandatory=$true, ParameterSetName='XML')]
[string]$Path
)
Switch ( $PSCmdlet.ParameterSetName )
{
Grid { Get-command | Out-GridView }
CSV { Get-Command | Export-CSV -Path $Path }
XML { Get-Command | Export-Clixml -Path $Path }
}
Hier sieht man auch einen nützlichen Anwendungsfall von Switch, denn die Abfrage der einzelnen Parametersätze ist so deutlich kompakter als mit mehreren If – ElseIf.