Tags: PowerShell, Scripts
Wie die meisten dynamischen Programmiersprachen lässt auch PowerShell dem Benutzer viele Freiheiten. Das vereinfacht die schnelle Entwicklung kurzer Scripts, fördert aber saloppen Programmierstil und daraus resultierende Probleme. Der Strict Mode beseitigt einige typische Fehlerquellen in PowerShell.
Beim Strict-Modus handelt es sich um kein Sicherheits-Feature im engeren Sinn, obwohl man damit Bugs vermeiden kann, die im ungünstigsten Fall zu Datenverlusten führen können. Sein primärer Zweck ist es, Fehler in Code zu unterbinden, der syntaktisch korrekt ist, aber zu unerwünschten Ergebnissen 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 Datentypen deklarieren müssen.
Während man in Perl den Strict-Modus getrennt für Variablen, Subs und Referenzen aktivieren kann, erwartet PowerShell hier eine Versionsnummer oder Off. Diese übergibt man dem Cmdlet Set-StrictMode.
Strict Mode 1.0
Die Nummer 1.0 verhindert die Verwendung von undeklarierten Variablen:
Set-StrictMode -Version 1.0
if( $a -gt 5 ){
Out-Host '$a ist größer 5'
}
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 Eigenschaften 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 Fehlermeldung auswerfen, weil diese keine Length-Eigenschaft haben.
Hier zeigt sich auch gleich die Zweischneidigkeit dieses Modus, weil er auch bei harmlosen Fällen Alarm schlägt. Ohne Strict Mode bekäme man die Verzeichnisse 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 Funktionsaufrufen. Die unterschiedliche 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 Programmiersprachen 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 Abbruchbedingung 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).
Setzt man etwa in einer function den Strict Mode auf Version 3.0, dann bleibt er auf der Konsole weiterhin beim Vorgabewert, nämlich ausgeschaltet. Umgekehrt würde die Eingabe von
Set-StrictMode -Version 3.0
auf der Kommandozeile 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.
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
- PowerShell für Logon-Scripts verwenden
- WhatIf, Confirm und Force: Ausführung von PowerShell-Cmdlets steuern
- ScriptRunner Portal Edition R5: Konfiguration von Abfragen, OpenID-Support, Web-API statt IIS
- ScriptRunner Portal Edition R4: Support für Microsoft Graph, überarbeitetes Portal, zentrale Execution-Policy
- Microsoft Graph: Einheitliches (PowerShell)-API für Microsofts Cloud-Dienste
Weitere Links