Skript-Debugging für die PowerShell (3)

Lesezeit
5 Minuten
Bis jetzt gelesen

Skript-Debugging für die PowerShell (3)

16.02.2026 - 07:00
Veröffentlicht in:

In PowerShell-Skripte für die Automatisierung der IT-Aufgaben schleichen sich unweigerlich Fehler ein. Das macht den IT-Verantwortlichen nicht gleich zu einem schlechten Skripter, er muss jedoch Bugs identifizieren und ausmerzen, bevor sie in der Produktionsumgebung für Chaos sorgen. Im dritten Teil vergleichen wir konkret das Debuggen in der Shell und das Debuggen im Editor.

Die PowerShell hat mehrere eingebaute Debugger. Einen sehr einfachen Code-Unterbrecher haben Sie bereits im Zusammenhang mit dem Write-Debug-Cmdlet kennengelernt. Einen weiteren Mini-Debugger aktivieren Sie mithilfe des Set-PSDebug-Befehls. Dieser bietet Ihnen drei Funktionalitäten, die oft bereits ausreichen, um einem Fehler auf die Schliche zu kommen.

  • "-Strict" schaltet den StrictMode in der Version 1.0 ein, was lediglich das Verwenden nicht initialisierter Variablen abfängt.
  • "-Step" hält die Ausführung nach jedem Befehl an, sodass Sie mit "H" denselben Mini-Debugger aktivieren können wie nach Write-Debug.
  • "-Trace" aktiviert die ausführliche Protokollierung aller ausgeführter Befehle. Die zulässigen Werte sind "0" (deaktiviert), "1" (grundlegendes Tracing) oder "2" (erweitertes Tracing). Die Tracing-Nachrichten wandern in den Debug-Stream, beeinträchtigen also nicht die normalen Ausgaben des Skripts.

Das eingestellte Debugging-Verhalten gilt für die gesamte PowerShell-Sitzung, somit auch für die interaktiven Befehle einschließlich Starten des zu untersuchenden Skripts. Um das Verhalten auf den Ursprungszustand zurückzusetzen, verwenden Sie einfach Set-PSDebug -Off.

Visual Studio Code mit geöffnetem PowerShell-Skript und aktivem Debugger inklusive Debug-Ansicht.
Bild 3: Der PowerShell-Debugger in VSCode findet Fehler und integriert sich zudem in Git.
 

Ein sehr nützlicher Befehl beim Troubleshooten komplexer Skripte und Module ist Get-PSCallStack. Damit erhalten Sie Zugriff auf alle nachfolgenden Skript- und Funktionsaufrufe, die zu der Stelle führen, an der der Debugger das Skript unterbrochen hat. Sie können diesen Befehl auch in Ihrem eigenen Code verwenden, um beispielsweise in Logdateien festzuhalten, welches Skript oder welche Funktion die gerade protokollierte Meldung erzeugt. Der unmittelbare Aufruf Ihrer Logging-Funktion lautet dabei

(Get-PSCallStack)[-1].Command.

Doch der PowerShell-Debugger ist viel flexibler als die zwei betrachteten Beispiele. Ein guter Ausgangspunkt für das Erforschen der Debugging-Funktionalität ist der about_Debuggers-Artikel. Achten Sie bei allen das PowerShell-Debugging betreffenden Microsoft-Dokumenten darauf, dass Sie die Ansicht auf diejenige PowerShell-Version schalten, mit der Sie tatsächlich arbeiten, denn der Debugger hat einige Erweiterungen und Verbesserungen erfahren, insbesondere in der siebten Generation der PowerShell.

Debuggen in der Shell

Um in den Debugger zu gelangen, können Sie entweder ein laufendes Skript in der Konsole mit "Strg+Break" unterbrechen. Dies ist besonders dann nützlich, wenn das Skript unerwartet lange läuft und Sie eine Dauerschleife vermuten. Oder Sie setzen einen Breakpoint über den Befehl Set-PSBreakpoint. In beiden Fällen ändert sich der PowerShell-Prompt – er erhält den Prefix "[DBG]:". Damit wissen Sie, dass Sie sich im Debugger befinden. Hier können Sie mit den Befehlen "s" oder "StepInto", "v" oder "StepOver" beziehungsweise "o" oder "StepOut" die Ausführung schrittweise fortsetzen. Weitere nützliche Befehle sind "l" oder "list" zum Anzeigen der gerade ausgeführten Stelle im Skript, "k" zum Aufruf von Get-PSCallStack und "Enter" zur Wiederholung des letzten Debugger-Befehls.

Sind Sie mit dem Troubleshooting fertig, können Sie mit "q" beenden oder mit "c" beziehungsweise "continue" oder "exit" ohne weitere Unterbrechungen fortsetzen. Aber Achtung: Die PowerShell-Dokumentation ist an dieser Stelle irreführend und setzt "exit" mit dem Debugger-Befehl "q" gleich. Zudem finden Sie darin noch den Befehl "stop", der in keiner der aktuellen PowerShell-Versionen existiert.

Das Setzen von Breakpoints in der PowerShell ist sehr flexibel. Neben der Möglichkeit, einen bestimmten Ort, also eine Zeile und optional sogar eine Spalte, in einem Skript oder Modul anzugeben, an dem die Ausführung unterbrochen werden soll, können Sie mit dem Set-PSBreakpoint-Befehl

  • Einen bestimmten Befehl, also ein Cmdlet oder eine Funktion, angeben, vor dessen Ausführung der Debugger einspringen soll. Dies geschieht mithilfe des Parameters "-Command", der übrigens auch Arrays akzeptiert, sodass Sie mehrere solche Breakpoints mit einem Befehl setzen können.
  • Eine oder mehrere Variablen über den Parameter "-Variable" hinterlegen, sodass beim Zugriff auf diese Variablen der Debugger einspringt. Dabei erlaubt "-Mode" die Angabe des Zugriffs, also Read, Write oder ReadWrite, der die Unterbrechung bewirken soll. Falls also eine Variable falsche Werte aufweist, können Sie gezielt nach den Stellen forschen, an denen ihr diese Werte zugewiesen werden.
  • Eine Aktion in Form eines Skriptblocks über "-Action" einbauen, die beim Erreichen des Breakpoints starten soll. Falls der Skriptblock nicht mit einem "break" endet, wird die Ausführung des Skripts tatsächlich nicht unterbrochen. Sie können den Skriptblock aber nutzen, um diagnostische Ausgaben zu tätigen und beispielsweise den Wert der gewünschten Variablen in eine Datei zu speichern. Geben Sie keine Aktion an, unterbricht die Ausführung und der Debugger-Prompt wird aktiviert.

Mit dem Get-PSBreakpoint-Befehl listen Sie die in der aktuellen Sitzung gesetzten Breakpoints auf. Die Cmdlets Enable-PSBreakpoint und Disable-PSBreakpoint erlauben es, Breakpoints zu aktivieren und zu deaktivieren, ohne sie löschen und neu anlegen zu müssen. Ein mit dem Set-PSBreakpoint-Cmdlet erstellter Breakpoint ist zunächst immer aktiv.

Debuggen im Editor

So mächtig der eingebaute PowerShell-Debugger auch ist, Skriptschreiber sind oft eher visuell veranlagt und kommen mit dem Debuggen an der Kommandozeile nicht immer gut zurecht. Um auch dieser Zielgruppe die Fehlersuche zu ermöglichen, halten alle IDEs, also Integrated Development Environments, auch einen grafischen Debugger bereit. Beliebte PowerShell-Editoren sind da keine Ausnahme.

Die mit Windows ausgelieferte PowerShell ISE ist im Großen und Ganzen nur ein Wrapper für den oben beschriebenen Konsolen-Debugger. Der Editor erlaubt lediglich das grafische Setzen, Löschen, Aktivieren und Deaktivieren von zeilenbasierten Breakpoints sowie die Hervorhebung der gerade ausgeführten Code-Zeile bei schrittweiser Ausführung. Ferner sind die meisten Debugger-Befehle mit Funktionstasten abgebildet, mit Ausnahme der Funktion zur Unterbrechung des laufenden Skripts. Diese heißt im englischen Originalmenü "Break All" und hört auf die Tastenkombination "Strg+B". Im deutschen Windows nennt sich der Menüpunkt "Alle trennen", die Tastenkombination ist im Menü nicht aufgeführt, funktioniert aber genauso gut wie in der englischen Fassung.

Eine deutliche Erweiterung der Funktionalität der ISE bietet das Modul "ISESteroids" des deutschen Entwicklers und PowerShell-Experten Dr. Tobias Weltner. Dieses erweitert die ISE um wichtige Funktionen wie Projektverwaltung, kontextsensitive Hilfe und auch Debugging-Werkzeuge wie Variableninspektion, Syntaxvorschläge und einiges mehr. Die Entwicklung des Moduls ist mittlerweile zum Stillstand gekommen, die aktuelle Version ist von 2019, nicht zuletzt deshalb, weil Visual Studio Code viele der Funktionen inzwischen adäquat abbildet. Wenn Sie jedoch in der ISE zu Hause sind und Ihre primäre Skriptumgebung die Windows-PowerShell ist, können Sie nach wie vor eine Lizenz für ISESteroids erwerben und für Ihre Skriptentwicklung nutzen.

Interessanterweise hat Microsoft nie den Debugging-Support für die PowerShell in das große Visual Studio eingebaut. Doch die kostenfreie kleine Schwester Visual Studio Code bietet mit der offiziellen PowerShell- und einigen weiteren Community-Erweiterungen exzellenten Support für das Schreiben und Troubleshooten von PowerShell-Skripten und -Modulen. Die Dokumentation bietet einen guten Überblick über die PowerShell-spezifischen Funktionen sowie einen Link zum zweiteiligen Blog von Keith Hill speziell über das Debuggen in VSCode. Neben der nativen PowerShell-Unterstützung bekommen Sie mit VSCode frei Haus weitere Features wie Git-Integration und Jupyter-Notebooks, die Ihre Möglichkeiten in puncto Verwalten und Verbreiten von Skriptcode noch einmal erweitern.

Spezialfälle im Debugging

Skripte, die für ein interaktives Ausführen in einer standardmäßigen Shell bestimmt sind, erlauben in der Regel schnelles und komfortables Debuggen mit guten Ergebnissen. Anders sieht es bei Skripten aus, die nur in einer bestimmten Umgebung überhaupt erst lauffähig sind, beispielsweise als Erweiterungsaktionen eines bestimmten Systems.

Ein Paradebeispiel hierfür sind Skripte, die in MDT- oder SCCM-Tasksequenzen laufen sollen und auf Objekte und Variablen der jeweiligen Umgebung angewiesen sind. In solchen Fällen müssen Sie oft die Klassen und Objekte, die außerhalb des Livesystems nicht vorhanden sind, emulieren, indem Sie sie vor oder während der Ausführung des Skripts in der Debugging-Umgebung erzeugen und entsprechenden Variablen zuweisen.

Ein weiterer Spezialfall ist das Debuggen von PowerShell-Skripten, die nicht in der Haupt-Shell laufen, sondern von dieser abgetrennt werden, um die asynchrone Ausführung mehrerer Skriptteile zu ermöglichen. Dies geschieht in der PowerShell entweder mittels Jobs oder mithilfe von Runspaces. Für beide Einsatzfälle hält die PowerShell entsprechende Cmdlets bereit, nämlich Debug-Job beziehungsweise Debug-Runspace, die Ihnen erlauben, den Konsolen-Debugger an einen laufenden Job beziehungsweise an einen aktiven Runspace anzuhängen. Das weitere Debuggen geschieht genau so wie das Debuggen des Hauptskripts an der Kommandozeile.

Fazit

Fehlerfreier Skriptcode ist ein Ziel, das ebenso wichtig anzustreben wie schwer zu erreichen ist. Besonders bei Skripten, die mit hohen Rechten und ohne Aufsicht laufen, sind Überraschungen sehr unangenehm und können zu Betriebsstörungen führen. Die PowerShell bietet einen eingebauten interaktiven Debugger, und die gängigen grafischen Entwicklungsumgebungen erweitern ihn um visuelle Hilfsmittel, die das Debugging um einiges erleichtern können. Machen Sie sich mit den vorgesehenen Debugging-Techniken vertraut, damit Ihnen das archaische "Debugging by printf()" erspart bleibt. (jp/ln)

Im ersten Teil unseres Workshops ging es um die Besonderheiten des PowerShell-Debugging und verbreitete Fehlerquellen. Im zweiten Teil haben wir uns angeschaut, wie Sie falsch eingesetzte Variablen vermeiden und warum Sie bei der Skriptentwicklung immer die vorhandene Infrastruktur berücksichtigen müssen.

Über den Autor: Evgenij Smirnov ist Senior Solutions Architect bei Semperis und Microsoft-MVP für Cloud & Datacenter Management sowie VMware Certified Implementation Expert für Datacenter-Virtualisierung.