Fehler in PowerShell vermeiden mit dem Strict Mode

    PowerShell Set-StrictModeWie die meisten dyna­mischen Programmier­sprachen lässt auch Power­Shell dem Benutzer viele Frei­heiten. Das ver­einfacht die schnelle Ent­wicklung kur­zer Scripts, fördert aber salop­pen Pro­grammier­stil und daraus resul­tierende Pro­bleme. Der Strict Mode beseitigt einige typische Fehler­quellen in PowerShell.

    Beim Strict-Modus handelt es sich um kein Sicherheits-Feature im engeren Sinn, obwohl man damit Bugs vermeiden kann, die im ungün­stigsten Fall zu Daten­verlusten führen können. Sein primärer Zweck ist es, Fehler in Code zu unter­binden, der syntaktisch korrekt ist, aber zu uner­wünschten Ergeb­nissen führt. Ihre Ursachen sind oft nur sehr schwer aufzuspüren.

    Versionen des Strict Mode

    Einen derartigen Mechanismus kennt Perl schon lange, und in VBScript kann man mit Option Explicit erzwingen, dass Variablen vor der ersten Verwendung deklariert werden. Allerdings geht dieses Korsett für Entwickler nicht so weit, dass sie etwa Daten­typen deklarieren müssen.

    Während man in Perl den Strict-Modus getrennt für Variablen, Subs und Referenzen aktivieren kann, erwartet PowerShell hier eine Version­snummer oder Off. Diese übergibt man dem Cmdlet Set-StrictMode.

    Strict Mode 1.0

    Die Nummer 1.0 verhindert die Verwendung von unde­klarierten Variablen:

    Set-StrictMode -Version 1.0

    if( $a -gt 5 ){
        Out-Host '$a ist größer 5'
        }

    Der Strict Mode 1.0 verhindert die Verwendung von nicht deklarierten Variablen.

    Nachdem $a in dem if-Ausdruck verwendet wird, ohne dass man ihr jemals einen Wert zugewiesen hat, produziert PowerShell an dieser Stelle eine Fehlermeldung.

    Strict Mode 2.0

    Die Version 2.0 prüft zusätzlich, ob nicht existierende Eigen­schaften eines Objekts referenziert werden. Das kann schon durch einen Tippfehler passieren oder dadurch, dass man es mit einem Mix von Objekten zu tun hat, bei dem ein Teil nicht über bestimmte Eigenschaften verfügt.

    Ein Beispiel dafür wäre, wenn man sich alle Dateien anzeigen lassen will, die eine bestimmte Größe übersteigen:

    Get-ChildItem | Where Length -gt 1GB

    Bei aktiviertem Strict Mode der Version 2.0 würde dieser Befehl bei allen Verzeichnissen eine Fehler­meldung auswerfen, weil diese keine Length-Eigenschaft haben.

    Der Strict Mode 2.0 verhindert das Verwenden von nicht vorhandenen Objekt-Eigenschaften.

    Hier zeigt sich auch gleich die Zwei­schneidigkeit dieses Modus, weil er auch bei harm­losen Fällen Alarm schlägt. Ohne Strict Mode bekäme man die Verzeich­nisse einfach nicht angezeigt.

    Anstatt ihn deswegen gleich zu vermeiden, müsste man in diesem Beispiel defensiver programmieren. Dabei könnte man etwa die Verzeichnisse über die Eigenschaft PSIsContainer ausfiltern:

    gci | Where {$_.PSIsContainer -eq $false -and $_.length -gt 1GB}

    Strict Mode 2.0 widmet sich zudem falschen Funktions­aufrufen. Die unter­schiedliche Syntax zum Aufruf von Methoden und Funktionen ist eine der beliebtesten Stolperfallen in PowerShell, besonders für solche Anwender, die häufig auch mit anderen Programmier­sprachen zu tun haben.

    Der Aufruf von

    myfunc(1, 2, 3)

    interpretiert die Argumente als ein Array anstatt als drei verschiedene Parameter (siehe dazu: PowerShell-Funktionen mit Parametern aufrufen).

    Strict Mode 3.0

    Schließlich gibt es noch eine Version 3.0 des Strict Mode, die aber nicht dokumentiert ist. Sie erhält man automatisch, wenn man

    Set-StrictMode -Version Latest

    in PowerShell 3.0 oder höher aufruft. Man kann aber hier auch explizit die "3.0" einsetzen.

    Zusätzlich zu den Kriterien der beiden anderen Versionen überprüft sie, ob Elemente eines Arrays mit einem ungültigen Index aufgerufen werden. Das kann relativ leicht passieren, wenn man in einer Schleife über die Elemente eines Arrays iteriert:

    Die Abbruch­bedingung für die Schleife ist mit

    $i -le 3

    definiert, wodurch auch $array[3] referenziert würde. Bei nur 3 Elementen ist der höchste Index aber 2. Der Strict Mode 3.0 fungiert also zusätzlich als Bounds Checker. Ohne ihn gäbe PowerShell hier den Wert $null aus.

    Gültigkeitsbereich des Strict Mode

    Schließlich wäre noch zu beachten, dass die Festlegung des Strict Mode immer nur für den jeweiligen und alle darunter liegenden Scopes gilt (siehe dazu: Gültigkeitsbereich (Scope) von Variablen in PowerShell).

    Der in der Funktion definierte Strict Mode gilt nicht für Aufrufe auf der Kommandozeile.

    Setzt man etwa in einer function den Strict Mode auf Version 3.0, dann bleibt er auf der Konsole weiterhin beim Vorgabe­wert, nämlich ausgeschaltet. Umgekehrt würde die Eingabe von

    Set-StrictMode -Version 3.0

    auf der Kommando­zeile dazu führen, dass PowerShell alle von dort gestarteten Scripts etwa darauf prüft, ob der höchste bzw. niedrigste Array-Index über- bzw. unterschritten wird.

    Keine Kommentare