Tags: PowerShell, Datei-Management
Die JavaScript Object Notation (JSON) hat sich als einfaches Textformat für den Austausch und die Serialisierung von Daten etabliert, unabhängig von Plattformen und Programmiersprachen. PowerShell spricht solche Strukturen als Objekte an und erspart dem User so das Parsen von Textdateien.
JSON ist neben XML, HTML und CSV ein weiteres Format, das PowerShell mit eigenen Cmdlets unterstützt. Da es relativ leichtgewichtig ist, bietet es sich bei einigen Anwendungen als Alternative zum relativ komplexen XML an.
Diese Eigenschaft könnte man sich zunutze machen, um Daten aus PowerShell-Scripts im JSON-Format zu speichern, sie später wieder aufzunehmen und weiter zu bearbeiten. Das gilt besonders für komplexere Strukturen wie etwa Hash-Tabellen.
Für die Umwandlung nach JSON ist das Cmdlet ConvertTo-Json zuständig, für den umgekehrten Weg gibt es ConvertFrom-Json.
Ausgabe von Cmdlets als JSON speichern
Zum Beispiel könnte man den Status aller Windows-Dienste, deren Name "remote" enthält, sowie einige zusätzliche Infos als JSON in einer Datei speichern:
Umgekehrt ließe sich diese Datei auf diese Weise einlesen:
$s = Get-Content -Raw -Encoding UTF8 services.json | ConvertFrom-Json
Die in $s als Eigenschaften eines Objekts gespeicherten JSON-Elemente lassen sich einfach so ansprechen:
$s.displayname
Damit würde man die Anzeigenamen aller Services ausgeben.
Konfiguration von Windows Terminal bearbeiten
Aus der Sicht der Systemverwaltung bedeutsam ist, dass sich JSON nicht nur als Format für den Datenaustausch etabliert hat, sondern immer häufiger als Syntax für Konfigurationsdateien verwendet wird. Beispiele dafür sind Mozilla Firefox oder Microsofts neues Windows Terminal.
Letzteres erfordert bis dato, dass man für die Konfiguration der verschiedenen Kommandozeilen die Datei profiles.json direkt bearbeitet. Anstatt dies manuell in einem Editor zu tun, könnte man zu PowerShell greifen und sich so das Hantieren mit Klammern, Kommata und Doppelpunkten ersparen.
Die Profile in der Konfiguration folgen diesem Muster:
Die Profile liegen somit als Array vor und jedes von ihnen wird spezifiziert durch mehrere Paare aus Name und Wert (zum Beispiel "commandline" und "powershell.exe"), die man in PowerShell als Hash-Tabelle darstellen kann.
Angenommen, man möchte beim ersten Profil die Kommandozeile für powershell.exe um eine Pfadangabe ergänzen, dann spricht man es über den Index [0] an und weist der Eigenschaft commandline einen neuen Wert zu:
Windows Terminal unterstützt zahlreiche Optionen für eine Kommandozeile, darunter Farben, Fonts oder Schriftgrößen. In der Standardkonfiguration sind diese aber nicht explizit gesetzt, so dass eine Zuweisung nach obigem Muster
$p.profiles[0].fontSize = "18"
zu einer Fehlermeldung führt, wonach das Objekt über diese Eigenschaft nicht verfügt.
Daher muss man für diesen Zweck ein eigenes Paar aus Name und Wert hinzufügen:
$p.profiles[0] | Add-Member -Name "fontSize" -Value "18" -MemberType NoteProperty
Möchte man hingegen eine Eigenschaft entfernen, so muss man die JSON-Repräsentation als PSObject ansprechen:
$p.profiles[0].PSObject.Properties.Remove("fontSize")
Neues Profil erstellen
Eine komplexere Aufgabe bestünde darin, ein neues Profil für ein Kommandozeilenprogramm hinzuzufügen, in unserem Beispiel für ftp.exe. Hier liegt es nahe, ein bestehendes Profil zu kopieren, anzupassen und an das vorhandene Array anzuhängen.
Hier zeigt sich, dass man in der Praxis oft unerwartete Hürden überwinden muss, auch wenn man es scheinbar mit einem standardisierten Format zu tun hat. So verwendet Windows Terminal in profiles.json Kommentare wie in Javascript, die einige Parser, darunter der von PowerShell, aber nicht akzeptieren. Diese muss man daher beim Einlesen ausfiltern, dafür bietet sich eine Regex an.
Außerdem stellt sich heraus, dass das Schreiben in die JSON-Datei per Redirect, wie im obigen Beispiel praktiziert, aus der Sicht von Windows Terminal zu einer ungültigen Struktur führt. Hier muss man über Out-File sicherstellen, dass als Zeichensatz UTF-8 verwendet wird.
Schließlich macht es PowerShell schwer, ein Array oder eines seiner Elemente zu kopieren. Zuweisungen an eine neue Variable übergeben immer nur eine Referenz, so dass sich Änderungen in der vermeintlichen Kopie stets auch auf das ursprüngliche Array auswirken.
Wenn man schon mit JSON arbeitet, kann man sich damit behelfen, indem man das gewünschte Element des Arrays in diesem Format zwischenspeichert und anschließend in eine neue Variable einliest.
JSON-Datei von Grund auf erstellen
Mit PowerShell muss man nicht immer nur auf eine vorhandene JSON-Datei zugreifen, um diese zu modifizieren. Vielmehr kann man die entsprechende Datenstruktur neu generieren und dann als JSON serialisieren.
Dieses Beispiel erzeugt eine Hash-Tabelle $h, in die ein weiterer Hashtable N und ein Array A eingebettet sind. Während es das Array gleich mit zwei Elementen initialisiert, erhält die Hash-Tabelle zwei Name-Wert-Paare erst im Nachhinein. Ein Cast mit [ordered] stellt zudem sicher, dass die zugewiesene Reihenfolge der Elemente erhalten bleibt.
Die Ausgabe sieht dann so aus:
Täglich Know-how für IT-Pros mit unserem Newsletter
Verwandte Beiträge
Weitere Links