Getty Images

Fehlermeldungen in PowerShell-Skripten optimieren

Die Verwendung regulärer Ausdrücke zum Prüfen von Eingabeinformationen und Generieren einer maßgeschneiderten Fehlermeldung in einem neuen Benutzerskript verhindert Supporttickets.

Wenn Sie Skripts für andere Personen schreiben, müssen Sie mit dem Unerwarteten rechnen.

Es ist eine nützliche Fähigkeit, bei der Skripterstellung in PowerShell Probleme zu erkennen und eine entsprechende Fehlermeldung auszugeben. Wenn Ihre Skripts von technisch nicht versierten Personen verwendet werden, müssen diese wissen, was sie falsch gemacht haben, wenn ihre Eingabe einen Fehler verursacht. Eine Möglichkeit, eine Funktion zu teste, ist die Validierung von Benutzereingaben. Das PowerShell-Attribut ValidatePattern erzeugt eine Fehlermeldung, wenn die Benutzereingabe nicht mit dem regulären Ausdruck übereinstimmt. Diese Methode der Validierung von Eingaben spart Zeit und reduziert Probleme, erfordert jedoch einige zusätzliche Codierung, um eine Fehlermeldung zu erzeugen, die für den Endbenutzer sinnvoll ist.

Was ist ValidatePattern?

Mit den erweiterten Funktionen in PowerShell können Sie mehrere Arten von Parametervalidierungen angeben.

Der erste ist der Parametertyp selbst. Wenn wir beispielsweise eine Zeichenfolge für einen bestimmten Parameter benötigen, verwenden wir den Typ [string], und die Funktion lässt nur die Übergabe von Zeichenfolgen an diesen Parameter zu.

Die zweite Form der Parametervalidierung erfolgt über die verschiedenen Validierungsaspekte, die verschiedene Aspekte des übergebenen Wertes bestätigen. Ein Validierungsattribut heißt ValidatePattern.

ValidatePattern vergleicht den übergebenen Parameter mit einem regulären Ausdruck und weist den Wert zurück, wenn er nicht übereinstimmt. ValidatePattern funktioniert bei anderen Parametertypen als Strings, indem es den Wert in einen String konvertiert und dann den Vergleich mit einem regulären Ausdruck durchführt. Bei Parametern, die keine Strings sind, kann es zu unerwarteten Ergebnissen kommen. Testen Sie daher gründlich, bevor Sie etwas in einer produktiven Live-Umgebung verwenden.

Wie man ValidatePattern verwendet

Da ValidatePattern Funktionsparameter prüft, wird es in einen param-Block eingefügt, der dem zu prüfenden Parameter ein Muster voranstellt.

Wenn wir zum Beispiel einen regulären Ausdruck für eine Telefonnummer verwenden, könnten wir einen Parameter wie den folgenden haben:

param (
    [ValidatePattern('\(?(?<areaCode>\d{3})\)?(-| )?(?<first>\d{3})(-| )?(?<second>\d{4})')]
    [string]$PhoneNumber
)

Die folgende Funktion wandelt eine übergebene Telefonnummer im US-Format in das richtige Format um:

Function Format-PhoneNumber {
    [OutputType([string])]
    param (
        [ValidatePattern('\(?(?<areaCode>\d{3})\)?(-| )?(?<first>\d{3})(-| )?(?<second>\d{4})')]
        [string]$PhoneNumber
    )
    $regex = '\(?(?<areaCode>\d{3})\)?(-| )?(?<first>\d{3})(-| )?(?<second>\d{4})'
    $phoneNumber -match $regex | Out-Null
    Write-Output "($($Matches.areaCode))-$($Matches.first)-$($Matches.second)"
}

Sie können die Funktion testen, indem Sie versuchen, eine ungültige Telefonnummer zu übergeben:

Format-PhoneNumber -PhoneNumber 123
Ausgabe einer Fehlermeldung
Abbildung 1: PowerShell gibt eine Fehlermeldung aus, wenn das ValidatePattern-Attribut eine fehlerhafte Eingabe erkennt.

Die Fehlermeldung ist nur sinnvoll, wenn Sie reguläre Ausdrücke lesen können, was ein Problem sein kann, je nachdem, wer die Meldung erhält. Stellen Sie sicher, dass Sie eine klare Hilfemeldung mit dem HelpMessage-Attribut schreiben:

param (
    [Parameter(
        HelpMessage = 'A phone number with 10 digits is expected.'
    )]
    [ValidatePattern('\(?(?<areaCode>\d{3})\)?(-| )?(?<first>\d{3})(-| )?(?<second>\d{4})')]
    [string]$PhoneNumber
)

Nun kann der Benutzer den Befehl Get-Help verwenden, um Hilfe zu erhalten:

Get-Help Format-PhoneNumber -Parameter PhoneNumber
Hinzufügen einer benutzerdefinierten Hilfemeldung
Abbildung 2: Durch Hinzufügen einer benutzerdefinierten Hilfemeldung erhält der Benutzer eine weniger technische Erklärung der gewünschten Eingabe für das PowerShell-Skript.

Wenn wir den richtigen Wert übergeben, wird die Funktion die Telefonnummer formatieren:

Format-PhoneNumber -PhoneNumber 1234567890
Formatierung der Eingabe nach der Validierungsprüfung
Abbildung 3: Nachdem die eingegebene Zahl die Validierungsprüfung bestanden hat, formatiert das Skript die Eingabe.

Ich habe diese Funktion für ein PowerShell-Skript geschrieben, das Benutzer aus einem Personalinformationssystem mit Active Directory und Microsoft Entra ID, ehemals Azure Active Directory, synchronisiert. In diesem Fall war das Telefonnummernfeld eine Zeichenfolge, die ein Benutzer in verschiedenen Formaten eingeben konnte, die die Funktion für das IT-System standardisieren sollte.

Wie prüft man die Eingabe von E-Mail-Adressen?

Stellen Sie sich vor, Sie haben eine ausgeklügelte Funktion geschrieben, die mehrere Aufgaben in Ihrer Infrastruktur ausführt – nur um am Ende fehlzuschlagen, weil Sie eine ungültige E-Mail-Adresse für die Benachrichtigung eingegeben haben.

Die Überprüfung von E-Mail-Adressen kann schwierig sein, je nachdem, wie genau Sie sie haben wollen. Die Website emailregex.com verwendet das folgende Format zur Überprüfung von E-Mail-Adressen:

Function Validate-EmailAddress {
    [cmdletbinding()]
    param (
        [ValidatePattern(@'
^(?(")(".+?(?<!\\)"@)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])@))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9][\-a-z0-9]{0,22}[a-z0-9]))$
'@
        )]
        [string]$EmailAddress
    )
}

Dieser reguläre Ausdruck funktioniert zwar, ist aber schwer zu verstehen. Vielleicht möchten Sie einen einfacheren regulären Ausdruck verwenden, der die Domäne Ihrer Organisation einschließt. Sie könnten stattdessen die Klasse System.Net.Mail.MailAdress verwenden:

Function Validate-EmailAddress {
    [cmdletbinding()]
    param (
        [System.Net.Mail.MailAddress]$EmailAddress
    )
}

In diesem Beispiel übernimmt .NET die Validierung. Das ist ein Beispiel dafür, dass man die Arbeit mit anderen Tools erledigen kann, anstatt einen komplizierten regulären Ausdruck zu schreiben, den man nicht versteht, wenn man ihn später überprüft.

Validierung von Datei- und Ordnereingaben

Vielleicht verwenden Sie bereits einen allgemeinen Parameter, um Pfade zu Dateien oder Ordnern zu akzeptieren. Wenn Sie sich den Pfad zu einer Datei oder einem Ordner ansehen, ist das eine gute Gelegenheit für einen regulären Ausdruck. Es ist jedoch besser, wenn Sie stattdessen die .NET-Typen für beide verwenden.

Für Dateien verwenden Sie System.IO.FileInfo und für Verzeichnisse System.IO.DirectoryInfo:

Function Validate-Path {
    [cmdletbinding()]
    param (
        [System.IO.FileInfo]$File,
        [System.IO.DirectoryInfo]$Folder
    )
}

Wenn Sie eine Datei mit einer bestimmten Erweiterung akzeptieren müssen, helfen reguläre Ausdrücke bei der Validierung. Im folgenden Beispiel nimmt das Skript eine CSV-Datei auf und einer der Parameter ist der Pfad zur CSV-Datei:

Function Ingest-CSV {
    [cmdletbinding()]
    param (
        [System.IO.FileInfo]$CsvPath
    )
}

Wir wissen, dass der Parameter $CsvPath mit .csv enden muss, so dass Sie den $-Anker in einem regulären Ausdruck verwenden können, das heißt am Ende einer Zeichenfolge:

'\.csv$'

In diesem Fall ist der Punkt in \. ein Escape-Zeichen in dem regulären Ausdruck.

Wenn der Objekttyp System.IO.FileInfo in einen String umgewandelt wird, erhalten wir den Pfad der Datei mit dem Befehl:

([System.IO.FileInfo]'C:\blah.txt').ToString()

In diesem Sinne können wir die gleiche Funktion Ingest-CSV verwenden, aber einfach das ValidatePattern hinzufügen:

Function Ingest-CSV {
    [cmdletbinding()]
    param (
        [ValidatePattern('\.csv$')]
        [System.IO.FileInfo]$CsvPath
    )
    $CsvPath
}

Wenn wir einen Nicht-CSV-Pfad übergeben, wird PowerShell eine Fehlermeldung genieren.

In einem anderen Beispiel können Sie überprüfen, ob ein Benutzer eine Datei innerhalb einer Dateifreigabe angibt. Beginnen Sie mit dem Anker ^, der den Beginn der Übereinstimmung anzeigt, und folgen Sie mit dem Freigabepfad, der entsprechend freigegeben ist. Wenn die Freigabe zum Beispiel \dc1\it-share\folder lautet, könnte Ihre Funktion wie folgt aussehen:

Function Validate-SharePath {
    [cmdletbinding()]
    param (
        [ValidatePattern('^\\\\dc1\\it-share\\folder')]
        [System.IO.FileInfo]$SharePath
    )
    $SharePath
}

Und wir können das testen, indem wir einen gültigen Pfad übergeben:

Validate-SharePath -SharePath \\dc1\it-share\folder\blah.txt

Wie Sie von ValidatePattern profitieren können

Das ValidatePattern-Attribut von PowerShell entfaltet ein großes Potenzial mit regulären Ausdrücken, insbesondere wenn Sie Funktionen in Skripts schreiben, die von anderen Personen verwendet werden. Ihre Skripts können viele unerwartete Eingaben reduzieren und den Arbeitsaufwand für das Neuschreiben von Code zur Anpassung an jedes mögliche Eingabeszenario verringern.

Die Parametervalidierung bietet eine weitere Schutzebene, damit eine Funktion wie erwartet ausgeführt wird, aber übertrieben Sie es nicht mit zu komplexen regulären Ausdrücken. Sie können die Parametervalidierung mit dem richtigen Objekttyp abdecken.

Sie können ValidatePattern in Verbindung mit anderen Typen als Strings verwenden – wie in den Beispielen für Dateitypen und Dateifreigaben gezeigt – also scheuen Sie sich nicht, etwas Kreatives auszuprobieren.

Erfahren Sie mehr über Serverbetriebssysteme