PowerShell & Scripting
PowerShell-Pipeline
Allgemeine Infos
Die PowerShell-Pipeline verbindet Befehle mit dem Operator |. Jeder Befehl gibt seine Ergebnisse an den nächsten weiter, die Befehle laufen von links nach rechts. Weil PowerShell .NET-Objekte mit Eigenschaften und Methoden überträgt, kann der empfangende Befehl direkt mit Feldern wie Name, Status oder LastWriteTime arbeiten.
Typische Pipeline-Bausteine sind Where-Object (filtern), Sort-Object (sortieren), Select-Object (Eigenschaften auswählen) und ForEach-Object (je Objekt eine Aktion ausführen). Am Ende stehen oft Export-Csv, ConvertTo-Json oder ein Format-Cmdlet für die Anzeige.
Abgrenzung: Die Unix-Pipe überträgt Textzeilen, die PowerShell-Pipeline Objekte. CI/CD-Pipelines in Azure DevOps oder GitHub Actions sind ein anderes Konzept und haben mit dem Pipe-Operator nichts zu tun.
Funktionsweise & Details
So bindet PowerShell Pipeline-Eingaben:
- Der linke Befehl schreibt Objekte in den Ausgabestrom.
- PowerShell sendet die Objekte einzeln an den nächsten Befehl. Übergibst Du dieselbe Sammlung als Parameterwert, kommt sie dagegen als ein einziges Array an.
- Der empfangende Parameter muss Pipeline-Eingaben annehmen, entweder ByValue (der Objekttyp passt oder lässt sich konvertieren) oder ByPropertyName (das Objekt hat eine Eigenschaft mit dem Namen des Parameters).
- Passt kein Parameter, schlägt die Bindung fehl. Trace-Command -Name ParameterBinding zeigt Schritt für Schritt, woran es liegt.
Ausnahmen von der automatischen Aufzählung: Hashtables und andere IDictionary-Typen musst Du explizit mit GetEnumerator() aufzählen, Strings zählt PowerShell nicht zeichenweise auf.
Vorteile & Nutzen
- Kein Textparsing: Eigenschaften bleiben typisiert, Datumsvergleiche und Zahlenfilter funktionieren direkt
- Streaming: Objekte werden einzeln verarbeitet, große Datenmengen müssen deshalb nicht komplett im Speicher liegen, bevor der nächste Befehl startet
- Lesbare Einzeiler: Abfragen wie „alle gestoppten Dienste mit Starttyp Automatisch“ bleiben in einer Zeile nachvollziehbar
- Kombinierbarkeit: Cmdlets aus unterschiedlichen Modulen arbeiten zusammen, solange die Parameter Pipeline-Eingaben annehmen
Praxisbeispiel
Ein Handelsunternehmen mit 120 Mitarbeitenden hat auf einem Dateiserver Logverzeichnisse, die unkontrolliert wachsen. Der Admin baut eine Pipeline aus Get-ChildItem, Where-Object (LastWriteTime älter als 90 Tage) und Remove-Item, zunächst mit -WhatIf, um die Trefferliste zu prüfen. Nach der Kontrolle läuft der Befehl als geplante Aufgabe jede Nacht. Ein zweiter Zweig der Pipeline schreibt die gelöschten Dateien mit Export-Csv in ein Protokoll.
Worauf sollte man achten?
- Früh filtern: Wenn das Quell-Cmdlet einen -Filter-Parameter hat, diesen nutzen statt erst später per Where-Object, das spart Laufzeit
- Format-Cmdlets nur ans Ende setzen, weil sie Formatierungsobjekte statt Daten ausgeben
- Mit Get-Help <Cmdlet> -Full prüfen, welche Parameter Pipeline-Eingaben ByValue oder ByPropertyName annehmen
- Hashtables vor der Pipeline mit GetEnumerator() aufzählen, sonst kommt nur ein einzelnes Objekt an
- Destruktive Pipelines (Remove-, Stop-, Set-) zuerst mit -WhatIf testen
Fazit
Die Pipeline ist das Grundprinzip von PowerShell und der Grund, warum Einzeiler so viel leisten. Wer Parameterbindung und frühes Filtern verstanden hat, schreibt schnellere und robustere Skripte.
Weiterführende Links
Verwandte Artikel
PowerShell
PowerShell | Artifact Registry ersetzt PowerShell Gallery
Microsoft 365
Microsoft 365 | PowerShell Security Audit - Teil 2: Mail-Schutz, Collaboration & Geräte
PHscripts.de | PSscripts.de
PowerShell-Update Radar: Was sich in Version 5 und 7 seit März 2025 getan hat
PHscripts.de | PSscripts.de