cherezoff - stock.adobe.com

PowerShell Debugging: Visual Studio Code versus Bordmittel

Für das Debugging der PowerShell stehen sowohl native Tools, als auch Visual Studio Code zur Verfügung. Dieser Artikel führt durch den Prozess und vergleicht beide Varianten.

In der PowerShell kann es schwer sein, das Debugging und das Schreiben von Skripten als Aufgabenbereiche zu trennen. Das Schreiben von Code in einer interpretierten Sprache macht es Admins leicht, jeden Schritt während des Schreibens auszuführen – dieser Prozess geht schnell in das Debugging über.

Es gibt zwei Varianten für das Debugging von PowerShell-Skripten: die interaktive PowerShell-Konsole selbst oder einer der zahlreichen PowerShell-Code-Editoren. Für kurze Skripte reichen die zahlreichen Debugging-Funktionen der PowerShell-Konsole aus, doch für längere Skripte oder gar Module, sollte ein Editor wie Visual Studio Code zum Einsatz kommen.

Zur Verdeutlichung enthält dieser Artikel ein Tutorial für das Debugging der PowerShell sowohl mit nativen Tools als auch mit Visual Studio Code. Durch die gewählten Beispiele soll verdeutlicht werden, welche Strategie wann die bessere ist.

Wann mit der PowerShell-Konsole debuggen?

Ein Beispiel: Sie schreiben einen Code-Snippet, um das aktuelle Verzeichnis nach JSON-Protokolldateien zu durchsuchen, die das Jahr 2020 im Namen tragen, und kopieren diese Dateien dann in ein anderes Verzeichnis.

Bevor Sie ein Skript in der Konsole ausführen, geben Sie einige Variablen als Befehle in die Konsole ein:

$sourceDir = 'C:\tmp\logs'

$targetDir = 'C:\logs'

Geben Sie dann den folgenden Einzeiler ein (Hinweis: Da Sie diesen Befehl interaktiv ausführen, ist es o. k., Aliase zu verwenden, bei denen es sich um Befehlskürzel oder alternative Namen handelt):

gci $sourceDir -filter *20*.json | %{copy $_.FullName -Destination $targetDir}

Beim Ausführen des Codes wird klar, dass er Dateien kopiert, die nicht geplant waren, nämlich Dateien aus dem letzten Jahr, obwohl im Cmdlet der Filter Get-ChildItem gesetzt ist, damit nur nach Dateien mit der Jahreszahl 20 gesucht wird. Um dies zu beheben, fügen Sie den Befehl Wait-Debugger hinzu, um in den Debugger zu wechseln:

gci $sourceDir -filter *20*.json | %{Wait-Debugger; copy $_ -Destination $targetDir}

Das sollte zu einem ähnlichen Ergebnis wie unten führen:

Abbildung 1: Die Ansicht beim Aufrufen des PowerShell-Debuggers.
Abbildung 1: Die Ansicht beim Aufrufen des PowerShell-Debuggers.

Jetzt haben Sie vollständigen Zugriff auf den PowerShell-Debugger. Verwenden Sie $_, um das aktuelle Element im Schleifen-Cmdlet ForEach-Object zu untersuchen.

Wie unten gezeigt, ist eine Datei aus dem Jahr 2019, aber sie geht durch den Filter, da sie im Namen die 20 enthält:

Abbildung 2: Die Datei kommt durch die Suche, da die Ziffernfolge 20 auch in 2019 enthalten ist.

Um dies zu überprüfen, verwenden Sie C, um zum nächsten Schritt überzugehen:

Abbildung 3: Mit der Eingabe von C wird das Skript bis zum nächsten Haltepunkt ausgeführt.
Abbildung 3: Mit der Eingabe von C wird das Skript bis zum nächsten Haltepunkt ausgeführt.

Beim nächsten Objekt handelt es sich wieder um eine Datei aus dem Jahr 2019. Beenden Sie also den Debugger mit q und korrigieren Sie den Code, um sicherzustellen, dass das neue Verzeichnis nur Dateien aus dem Jahr 2020 enthält:

gci $sourceDir -filter 2020*.json | %{copy $_.FullName -Destination $targetDir}

Es ist möglich, dieses Snippet noch etwas ausgefeilter zu gestalten – zum Beispiel, damit es den Inhalt der Datei überprüft, um sicherzustellen, dass der Zeitstempel in der Protokolldatei auch aus 2020 stammt. PowerShell ermöglicht es Admins, lange Einzeiler zu schreiben, aber sie werden schnell unhandlich, besonders wenn es sie zu debuggen gilt.

Es ist möglich, ein mehrzeiliges Skript interaktiv in PowerShell zu schreiben. Nach jedem Befehl kann durch das gleichzeitige Drücken der Umschalt- und Eingabetaste in eine neue Zeile gewechselt werden. Das war es dann aber auch schon in Sachen Übersichtlichkeit: die Konsole bietet nur grundlegende Textbearbeitungsfunktionen.

Für fortgeschrittenere Funktionen ist es deshalb am besten, zum Debuggen auf Visual Studio Code umzusteigen.

Wann in Visual Studio Code debuggen?

Im gewählten Beispiel enthalten die JSON-Protokolldateien ein Array, in dem das erste Element das Datum der Erstellung der Datei ist. Zum Beispiel:

[

    "2020-01-17 18:05:01.325248",

    {...

Erweitern Sie das Skript aus dem vorigen Abschnitt, damit auch dort das Datum überprüft wird:

$sourceDir = 'C:\tmp\logs'

$targetDir = 'C:\logs'

$files = Get-ChildItem $sourceDir -filter 2020*.json

foreach ($file in $files) {

    $json = Get-Content $file.FullName | ConvertTo-Json

    if ($json[0] -like '2020*') {

        Copy-Item $file.FullName -Destination $targetDir

    }

}

In Zeile sechs sehen wir das erste Element in der konvertierten JSON-Matrix. Leider werden nach der Ausführung des Codes keine Dateien im Zielverzeichnis angezeigt; es ist Zeit für mehr PowerShell-Debugging.

Setzen Sie den Cursor auf Zeile sechs und drücken Sie F9 auf der Tastatur, um einen Haltepunkt hinzuzufügen: Wenn der Code auf diese Zeile trifft, wird er im Debugger im Terminal abgelegt. Beachten Sie den roten Punkt links neben der Zeile:

Abbildung 4: Der rote Punkt markiert einen Haltepunkt im Code.
Abbildung 4: Der rote Punkt markiert einen Haltepunkt im Code.

Nachdem der Haltepunkt gesetzt ist, drücken Sie F5, um den Code auszuführen. Wenn Sie durch den Debugger-Bereich blättern, sehen Sie die Werte aller Variablen im Skript auf der linken Seite anzeigt:

Abbildung 5: Im Debugger werden auf der linken Seite die Werte der Variablen im Skript angezeigt.
Abbildung 5: Im Debugger werden auf der linken Seite die Werte der Variablen im Skript angezeigt.

Sie können die aktuelle $file, die Anzahl der Objekte im Array $files und sogar die $json-Variable sehen. Um die $json-Variable genauer zu betrachten, wählen Sie die gleichen PowerShell-Debugging-Funktionen von der Konsole im Terminal aus. Eingabe:

$json[0]

Die unten gezeigten Ergebnisse entsprechen nicht den Erwartungen, da das erste Element in der $json-Variablen ein [ anstelle des Datums ist:

Abbildung 6: Anstelle der eckigen Klammer sollte eigentlich das Datum stehen.
Abbildung 6: Anstelle der eckigen Klammer sollte eigentlich das Datum stehen.

Um zu sehen, was für ein Objekttyp $json ist, fahren Sie mit der Maus über die Variable im Debugger-Fenster oder untersuchen Sie die Variable direkt. In beiden Fällen wird ein String angezeigt:

Abbildung 7: Es wird ein String angezeigt statt des erwarteten Objekts.
Abbildung 7: Es wird ein String angezeigt statt des erwarteten Objekts.

Das Cmdlet ConvertFrom-Json sollte jedoch ein Objekt – wie in diesem Beispiel beabsichtigt – und keinen String erzeugen. Dies liegt daran, dass wir – wenn wir uns das Skript vom Anfang dieses Abschnitts erneut ansehen – versehentlich ConvertTo-Json anstelle von ConvertFrom-Json verwenden.

Der korrigierte Code sollte wie folgt aussehen:

$sourceDir = 'D:\UtoData'

$targetDir = 'C:\logs'

$files = Get-ChildItem $sourceDir -filter 2020*.json

foreach ($file in $files) {

    $json = Get-Content $file.FullName | ConvertFrom-Json

    if ($json[0] -like '2020*') {

        Copy-Item $file.FullName -Destination $targetDir

    }

}

Lassen Sie den Haltepunkt auf Zeile sechs und führen Sie den Code mit F5 erneut aus und sehen Sie sich die Variable $json noch einmal an:

Abbildung 8: Nach der Korrektur wird wie gewünscht ein Objekt angezeigt statt eines Strings.
Abbildung 8: Nach der Korrektur wird wie gewünscht ein Objekt angezeigt statt eines Strings.

Die Ergebnisse sehen jetzt wie erwartet aus, da wir jetzt ein Objekt statt eines Strings haben. Dies bedeutet, dass ConvertFrom-Json funktioniert hat. Um den Haltepunkt zu entfernen, setzen Sie den Cursor wieder auf Zeile sechs und drücken Sie F9. Drücken Sie jetzt wieder F5, und der Code wird wie beabsichtigt ausgeführt.

Nächste Schritte

Lohnt sich der Umstieg auf die PowerShell 7?

Die drei wichtigsten PowerShell-Tutorials für Admins.

Die neuen Fehlerbehandlungs-Tools der PowerShell 7.

Erfahren Sie mehr über Data-Center-Betrieb