Wenn Sie ein PowerShell-Skript oder eine Funktion schreiben, möchten Sie oft Benutzereingaben über Parameter akzeptieren. Wenn Sie die Werte, die diese Parameter akzeptieren, nicht einschränken, können Sie nicht garantieren, dass es Situationen gibt, in denen unangemessene Werte bereitgestellt werden. In diesem Artikel erfahren Sie, wie Sie das PowerShell-Parametervalidierungsattribut ValidateSet verwenden, um diese Werte auf nur die von Ihnen definierten zu beschränken.
Beim Schreiben eines PowerShell-Skripts oder einer Funktion können Sie viele verschiedene Validierungsattribute verwenden, um zu überprüfen, ob die Werte, die Ihren Parametern übergeben werden, akzeptabel sind, und den Benutzer benachrichtigen, wenn dies nicht der Fall ist.
Dieser Artikel konzentriert sich auf das Validierungsattribut ValidateSet. Sie erfahren, was ValidateSet bewirkt, warum Sie ValidateSet in Ihrem Code verwenden möchten und wie Sie dies tun können. Sie erfahren auch mehr über die Tabulatorvervollständigungsfunktion, die durch ValidateSet aktiviert wird und Benutzern Ihres Codes dabei hilft, gültige Parameterwerte bereitzustellen.
PowerShell ValidateSet: Eine kurze Übersicht
ValidateSet ist ein Parameterattribut, mit dem Sie eine Reihe von Elementen definieren können, die nur als Wert für diesen Parameter akzeptiert werden.
Zum Beispiel haben Sie möglicherweise ein Skript, das mit Active Directory-Domänencontrollern funktioniert. Dieses Skript verfügt über einen Parameter, der den Namen eines Domänencontrollers angibt. Wäre es nicht sinnvoll, die Liste der akzeptablen Werte auf die tatsächlichen Namen der Domänencontroller zu beschränken? Es gibt keinen Grund, warum der Benutzer „foobar“ als Wert verwenden sollte, wenn Sie im Voraus wissen, welche Werte das Skript benötigt. ValidateSet gibt Ihnen diese Möglichkeit.
Anforderungen
Dieser Artikel wird ein Lernleitfaden sein. Wenn Sie mitmachen möchten, benötigen Sie Folgendes:
- Visual Studio Code oder einen anderen Code-Editor. Ich werde Visual Studio Code verwenden.
- Mindestens PowerShell 5.1 für den Großteil des Codes in diesem Artikel. Es gibt einen Abschnitt, der PowerShell 6.1 oder neuer erfordert, und ich werde das kennzeichnen, wenn wir dazu kommen.
Der gesamte Code in diesem Artikel wurde in den folgenden Umgebungen getestet:
Operating System | PowerShell Versions |
---|---|
Windows 7 SP1 | 5.1, Core 6.2 |
Windows 10 1903 | 5.1, Core 6.2 |
Linux Mint 19.2 | Core 6.2 |
Um die Konzepte rund um ValidateSet zu erklären, werden Sie ein kleines Skript namens Get-PlanetSize.ps1 erstellen. Dieses Skript liefert Informationen über die Größen der Planeten in unserem Sonnensystem.
Sie beginnen mit einem einfachen Skript und verbessern nach und nach seine Fähigkeit, Eingaben vom Benutzer zu verarbeiten, und erleichtern ihnen die Entdeckung möglicher Parameterwerte.
Erste Schritte
Um loszulegen, kopieren Sie den untenstehenden PowerShell-Code in Ihren bevorzugten Texteditor und speichern Sie ihn als Get-PlanetSize.ps1.
Führen Sie das Skript von einer PowerShell-Eingabeaufforderung aus und Sie sollten Folgendes erhalten:
Informativ, aber nicht sehr flexibel; die Informationen für jeden Planeten werden zurückgegeben, auch wenn Sie nur die Informationen für den Mars möchten.
Vielleicht möchten Sie die Möglichkeit haben, einen einzelnen Planeten anzugeben, anstatt alle zurückzugeben. Dies können Sie durch Einführung eines Parameters erreichen. Schauen wir uns an, wie das funktioniert.
Eingabe mit Parameter akzeptieren
Um das Skript die Annahme eines Parameters zu ermöglichen, fügen Sie dem Anfang des Skripts einen Param()
-Block hinzu. Nennen Sie den Parameter Planet
. Ein geeigneter Param()
-Block sieht wie folgt aus.
Im folgenden Beispiel stellt die Zeile [Parameter(Mandatory)]
sicher, dass immer ein Planetenname an das Skript übergeben wird. Wenn er fehlt, wird das Skript danach fragen.
Der einfachste Weg, um diesen Planet
-Parameter in das Skript einzubeziehen, besteht darin, die Zeile $planets.keys | Foreach-Object {
in $Planet | Foreach-Object {
zu ändern. Nun sind Sie nicht mehr auf die zuvor statisch definierte Hashtable angewiesen, sondern lesen den Wert des Planet
-Parameters.
Wenn Sie das Skript ausführen und einen Planeten mit dem Planet
-Parameter angeben, sehen Sie nur Informationen über diesen bestimmten Planeten.
Hervorragend. Skript abgeschlossen? Vielleicht doch nicht.
Die Optionen sind zu offen
Was passiert, wenn Sie versuchen, den Durchmesser des Planeten Barsoom mit dem Skript Get-PlanetSize.ps1 zu finden?
Hmm, das ist nicht richtig. Barsoom steht nicht auf der Liste der Planeten, aber das Skript wird trotzdem ausgeführt. Wie können wir das beheben?
Das Problem hierbei ist, dass das Skript jede Eingabe akzeptiert und verwendet, unabhängig davon, ob es ein gültiger Wert ist oder nicht. Das Skript benötigt eine Möglichkeit, die akzeptierten Werte für den Planet
-Parameter einzuschränken. Geben Sie ValidateSet ein!
Stellen Sie sicher, dass nur bestimmte Werte verwendet werden
A ValidateSet list is a comma-separated list of string values, wrapped in single or double-quotes. Adding a ValidateSet attribute to a script or function parameter consists of adding a line of text to the Param()
block, as shown below. Replace the Param()
block in your copy of Get-PlanetSize.ps1 with the one below and save the file.
Versuchen Sie, das Skript erneut mit Barsoom als Planet
-Parameter auszuführen. Jetzt wird eine hilfreiche Fehlermeldung zurückgegeben. Die Meldung gibt an, was schief gelaufen ist, und liefert sogar eine Liste möglicher Werte für den Parameter.
Machen Sie ValidateSet in PowerShell Groß- und Kleinschreibung beachtend
Standardmäßig ist das ValidateSet-Attribut in Bezug auf die Groß- und Kleinschreibung nicht beachtend. Das bedeutet, dass es jeden String akzeptiert, solange er in der erlaubten Liste steht, unabhängig von der Groß- und Kleinschreibung. Zum Beispiel würde das obige Beispiel sowohl Mars
als auch mars
akzeptieren. Wenn erforderlich, können Sie ValidateSet dazu zwingen, die Groß- und Kleinschreibung zu beachten, indem Sie die Option IgnoreCase
verwenden.
Die IgnoreCase
-Option in ValidateSet, einer Validierungsattribut, bestimmt, ob die an den Parameter übergebenen Werte genau mit der Liste der gültigen Werte übereinstimmen. Standardmäßig ist IgnoreCase
auf $True
(Groß- und Kleinschreibung ignorieren) eingestellt. Wenn Sie dies auf $False
setzen, würde die Angabe von mars als Wert für den Planet
-Parameter für Get-PlanetSize.ps1
eine Fehlermeldung generieren.
Sie würden die IgnoreCase
-Option verwenden, indem Sie ihr einen Wert von $true
am Ende der Liste der gültigen Werte zuweisen, wie unten gezeigt.
Jetzt, wenn Sie versuchen, einen Wert für Planet
zu verwenden, der nicht genau wie ein Wert in der Liste ist, schlägt die Validierung fehl.
Verwendung der Tab-Vervollständigung
Ein weiterer Vorteil der Verwendung von ValidateSet besteht darin, dass Sie die Tab-Vervollständigung verwenden können. Dies bedeutet, dass Sie mit der TAB-Taste durch die möglichen Werte für einen Parameter navigieren können. Dies verbessert die Benutzerfreundlichkeit eines Skripts oder einer Funktion erheblich, insbesondere von der Konsole aus.
In den folgenden Beispielen gibt es ein paar Dinge zu beachten:
- Die Tab-Vervollständigung kehrt nach Anzeige des letzten Wertes zum ersten Wert zurück.
- Die Werte werden alphabetisch sortiert angezeigt, obwohl sie nicht alphabetisch in der ValidateSet aufgeführt sind.
- Durch Eingabe eines Anfangsbuchstabens und Drücken der TAB-Taste werden die Werte, die von der Tab-Vervollständigung angeboten werden, auf diejenigen eingeschränkt, die mit diesem Buchstaben beginnen.


Sie können auch die Tab-Vervollständigung von ValidateSet in der PowerShell Integrated Scripting Environment (ISE) nutzen, wie im folgenden Beispiel gezeigt. Die ISE Intellisense-Funktion zeigt Ihnen die Liste der möglichen Werte in einer schönen Auswahlbox an.
Intellisense gibt alle Werte zurück, die den eingegebenen Buchstaben enthalten, nicht nur diejenigen, die damit beginnen.

Jetzt, da wir die ValidateSet-Validierungsattribute in Windows 5.1 behandelt haben, werfen wir einen Blick darauf, was in PowerShell Core 6.1 hinzugefügt wurde und sehen, ob dies unserem Skript weitere Validierungsmöglichkeiten bietet.
Verständnis der Änderungen an ValidateSet in PowerShell 6.1
Mit der Einführung von PowerShell Core 6.1 wurden zwei neue Funktionen zu den Validierungsattributen ValidateSet hinzugefügt:
- Die Eigenschaft „ErrorMessage“
- Verwendung von Klassen in ValidateSet über den Zugriff auf „System.Management.Automation.IValidateSetValuesGenerator“
Die ErrorMessage-Eigenschaft
Die standardmäßige Fehlermeldung, die angezeigt wird, wenn Sie einen falschen Planetennamen an „Get-PlanetSize.ps1“ übergeben, ist hilfreich, aber etwas umständlich:
Verwenden Sie die „ErrorMessage“-Eigenschaft des Validierungsattributs „ValidateSet“, um eine andere Fehlermeldung festzulegen, wie im folgenden Beispiel gezeigt. „{0}“ wird automatisch durch den übergebenen Wert ersetzt und „{1}“ wird automatisch durch die Liste der erlaubten Werte ersetzt.
Ersetzen Sie den „Param()“-Block in der Skriptdatei und speichern Sie sie. Versuchen Sie dann erneut, „Get-PlanetSize.ps1 -Planet Barsoom“ auszuführen. Beachten Sie, dass der Fehler jetzt weniger umständlich und aussagekräftiger ist.
Als nächstes werfen Sie einen Blick auf eine neue Möglichkeit, die akzeptablen Werte in ValidateSet über eine PowerShell Klasse zu definieren.
PowerShell-Klassen
Benutzerdefinierte Typen, in PowerShell als Klassen bekannt, sind seit Version 5 verfügbar. Mit der Einführung von PowerShell Core 6.1 gibt es eine neue Funktion, die die Verwendung einer Klasse zur Bereitstellung der Werte für ValidateSet ermöglicht.
Die Verwendung einer Klasse ermöglicht es Ihnen, die Hauptbeschränkung eines ValidateSet zu umgehen – es ist statisch. Das heißt, es ist als Teil der Funktion oder des Skripts eingebettet und kann nur durch Bearbeiten des Skripts selbst geändert werden.
Die neue Funktion, die mit ValidateSet funktioniert, ist die Möglichkeit, die Klasse System.Management.Automation.IValidateSetValuesGenerator zu verwenden. Wir können dies als Grundlage für unsere eigenen Klassen verwenden, indem wir Vererbung verwenden. Um mit ValidateSet zu arbeiten, muss die Klasse auf System.Management.Automation.IValidateSetValuesGenerator basieren und eine Methode namens GetValidValues implementieren.
Die Methode GetValues gibt die Liste der Werte zurück, die Sie akzeptieren möchten. Ein Param-Block mit der statischen Liste der Planeten, die durch eine [Planet]-Klasse ersetzt wird, würde wie folgt aussehen. Dieses Beispiel funktioniert noch nicht. Lesen Sie weiter, um herauszufinden, wie Sie dies implementieren können.
Verwendung einer Klasse für eine ValidateSet-Werteliste: Ein echtes Beispiel
Um die Verwendung einer Klasse für eine ValidateSet-Werteliste zu demonstrieren, ersetzen Sie die statische Liste der Planeten, die zuvor verwendet wurde, durch eine aus einer CSV-Textdatei geladene Liste. Sie müssen nicht mehr eine statische Liste von Werten im Skript selbst pflegen!
Erstellen einer Datenquelle für die Klasse
Zunächst müssen Sie eine CSV-Datei erstellen, die jeden der gültigen Werte enthält. Kopieren Sie dazu diesen Datensatz in eine neue Textdatei und speichern Sie ihn als planets.csv im selben Ordner wie das Skript Get-PlanetSize.ps1.
Hinzufügen der Klasse zum Skript
Jede von ValidateSet verwendete Klasse muss bereits definiert sein, bevor ValidateSet versucht, sie zu verwenden. Das bedeutet, dass die Struktur von Get-PlanetSize.ps1 wie sie ist, nicht funktionieren wird.
Die Klasse [Planet] muss definiert sein, bevor sie verwendet werden kann, daher muss sie am Anfang des Skripts stehen. Eine geeignete Skelett-Klassendefinition sieht wie folgt aus:
In der Methode GetValidValues() der Klasse verwenden Sie das Import-CSV-Cmdlet, um die zuvor erstellte Textdatei planets.csv zu importieren. Die Datei wird in einer Variablen mit globalen Gültigkeitsbereich namens $planets importiert, um später im Skript darauf zugreifen zu können.
Verwenden Sie die Rückgabeanweisung, um die Liste der Planetennamen über GetValidValues() zurückzugeben. Nach diesen Änderungen sollte die Klasse jetzt wie folgt aussehen:
Entfernen Sie als nächstes die Deklaration der $planets-Hashtabelle aus dem Skript, wie unten gezeigt. Die globale Variable $planets, die von der Klasse [Planet] befüllt wird, enthält die Planetendaten.
Verpacken Sie den verbleibenden ursprünglichen Code nun in einer Funktion und nennen Sie sie Get-PlanetDiameter, um sie vom Namen des Skripts zu unterscheiden. Platzieren Sie den Param()-Block, der am Anfang des Skripts stand, innerhalb der Funktion. Ersetzen Sie die statische Liste der Planeten durch einen Verweis auf die Klasse [Planet], wie unten gezeigt.
Ersetzen Sie die Zeile $output = "Der Durchmesser des Planeten {0} beträgt {1} km" -f $_, $planets[$_]
durch die folgenden beiden Zeilen. Diese ermöglichen es dem Skript, einen Planeten im Array der durch Import-CSV
erstellten Objekte nachzuschlagen, anstatt der zuvor erstellten Hash-Tabelle, die Sie aus dem Skript entfernt haben:
Nach dieser Änderung sollte Ihr endgültiges Skript wie folgt aussehen:
Beachten Sie, dass das Skript ab diesem Punkt nur in PowerShell 6.1 oder höher funktioniert
Wie verwenden Sie nun dieses Skript?
Ausführen des Skripts
Sie können die neue Version des Skripts nicht einfach ausführen. Der gesamte nützliche Code ist nun in einer Funktion verpackt. Stattdessen müssen Sie die Datei dot-sourcen, um auf die Funktion aus der PowerShell-Sitzung zugreifen zu können.
Nach dem Dot-Sourcing haben Sie nun Zugriff auf die neue Funktion Get-PlanetDiameter
in der PowerShell-Sitzung, mit Tab-Vervollständigung.
„Was ist der Nutzen dieser Arbeit?“, höre ich Sie fragen. „Das Skript scheint auf die gleiche Weise zu funktionieren, aber es ist schwieriger, den Code zu verwenden!“
Versuchen Sie Folgendes:
- Öffnen Sie die zuvor erstellte Datei
planets.csv
. - Fügen Sie eine neue Zeile mit einem neuen Namen und Durchmesser hinzu.
- Speichern Sie die CSV-Datei.
In derselben Sitzung, in der Sie Ihr Skript ursprünglich dot sourcten, versuchen Sie, den Durchmesser des neuen Planeten mit Get-PlanetDiameter
nachzuschlagen. Es funktioniert!
Die Verwendung einer Klasse auf diese Weise bietet uns mehrere Vorteile:
- Die Liste der gültigen Werte ist nun vom Code selbst getrennt, aber Änderungen an den Werten in der Datei werden vom Skript erkannt.
- Die Datei kann von jemandem gepflegt werden, der niemals auf das Skript zugreift.
- A more complex script could look up information from a spreadsheet, database, Active Directory or a web API.
Wie Sie sehen können, sind die Möglichkeiten nahezu endlos, wenn Sie eine Klasse verwenden, um ValidateSet-Werte bereitzustellen.
Zusammenfassung
Wir haben viel erreicht, während wir Get-PlanetSize.ps1
erstellt haben, also fassen wir zusammen.
In diesem Artikel haben Sie gelernt:
- Was ein ValidateSet-Validierungsattribut ist und warum Sie es verwenden möchten
- Wie man ValidateSet zu einer PowerShell-Funktion oder einem Skript hinzufügt
- Wie die Tab-Vervollständigung mit ValidateSet funktioniert
- Wie man die Eigenschaft
IgnoreCase
verwendet, um festzulegen, ob Ihr ValidateSet die Groß-/Kleinschreibung beachtet - Wie man die Eigenschaft
ErrorMessage
mit Ihrem ValidateSet und PowerShell 6.1 verwendet - Wie man eine Klasse verwendet, um ein dynamisches ValidateSet mit PowerShell 6.1 zu erstellen
Worauf warten Sie noch? Fangen Sie noch heute an, ValidateSet zu verwenden!
Weiterführende Informationen
Source:
https://adamtheautomator.com/powershell-validateset/