PowerShell-Fehlerbehandlung (Error Handling)

Overview

PowerShell kennt drei Fehlerarten: Nicht terminierende Fehler landen im Fehlerstrom, das Skript läuft weiter (Standard bei Write-Error und vielen Cmdlets). Anweisungsterminierende Fehler stoppen die aktuelle Anweisung, etwa bei .NET-Ausnahmen. Skriptterminierende Fehler brechen die gesamte Aufrufkette ab, zum Beispiel throw oder Fehler mit -ErrorAction Stop.

try/catch fängt nur terminierende Fehler. Damit ein Cmdlet-Fehler im catch-Block ankommt, setzt Du -ErrorAction Stop am Aufruf oder $ErrorActionPreference = 'Stop' für den Gültigkeitsbereich. Mögliche Werte sind Break, Continue (Standard), Ignore, Inquire, SilentlyContinue und Stop.

Native Programme wie robocopy melden Fehler über Exitcodes in $LASTEXITCODE. Seit PowerShell 7.4 gibt es $PSNativeCommandUseErrorActionPreference: Steht die Variable auf $true, erzeugen Exitcodes ungleich 0 Fehler nach $ErrorActionPreference. Standard ist $false.

How it works

Aufbau einer robusten Fehlerbehandlung:

  1. Riskante Aufrufe in einen try-Block setzen und dort -ErrorAction Stop verwenden.
  2. Spezifische Ausnahmen zuerst fangen, etwa catch [System.IO.FileNotFoundException], danach allgemeinere Typen. Nur der erste passende catch-Block läuft.
  3. Im catch-Block steht der Fehler als ErrorRecord in $_ bzw. $PSItem. Für Logs eignen sich $_.ToString(), $_.InvocationInfo (Skript, Zeile) und $_.ScriptStackTrace.
  4. Der finally-Block läuft immer, ob ein Fehler auftrat oder nicht. Dort gehören Aufräumarbeiten hin, etwa Verbindungen schließen oder Sitzungen trennen.
  5. Eigene Fehler wirfst Du mit throw oder mit Write-Error -Exception, damit Aufrufer sie nach Typ fangen können.

trap ist ein älterer Mechanismus, der alle Ausnahmen eines Gültigkeitsbereichs abfängt. Er eignet sich für Skripte, die alles protokollieren und weiterlaufen sollen.

Benefits

  • Kontrollierte Abbrüche: Skripte stoppen an der richtigen Stelle, statt mit halb verarbeiteten Daten weiterzulaufen
  • Sauberes Aufräumen: finally schließt Verbindungen und Sitzungen auch im Fehlerfall, offene Sitzungen blockieren sonst Ressourcen
  • Aussagekräftige Logs: Zeilennummer und Stacktrace aus dem ErrorRecord verkürzen die Fehlersuche
  • Einheitliche Behandlung von Exitcodes: Mit $PSNativeCommandUseErrorActionPreference fließen native Tools in dieselbe Logik ein

Practical example

Ein Großhändler mit 200 Mitarbeitenden exportiert jede Nacht Artikeldaten per Skript aus dem ERP auf einen SFTP-Server. Bisher lief das Skript bei einem Netzwerkfehler einfach weiter und lieferte leere Dateien aus. Der Admin setzt die kritischen Schritte in try-Blöcke mit -ErrorAction Stop, schreibt Fehler mit Zeilennummer ins Log und schickt eine Meldung an das Ticket-System. Im finally-Block trennt das Skript die Verbindung. Leere Exporte gehören damit der Vergangenheit an.

Things to keep in mind

  • -ErrorAction SilentlyContinue nicht pauschal setzen: Fehler verschwinden dann still und fallen erst beim Ergebnis auf
  • Exitcodes von robocopy beachten: Werte bis 7 sind informativ, erst ab 8 liegt ein Fehler vor, deshalb lokal $PSNativeCommandUseErrorActionPreference = $false setzen und selbst prüfen
  • Spezifische Ausnahmetypen vor Basistypen wie IOException fangen
  • In unbeaufsichtigten Skripten jeden catch-Block protokollieren lassen, damit Fehler im Monitoring sichtbar werden

Conclusion

Ohne Fehlerbehandlung sind Automatisierungsskripte ein Risiko, weil sie Fehler verschweigen. try/catch mit -ErrorAction Stop und sauberem Logging gehört in jedes Produktivskript.