OutVariable, PipelineVariable: Ausgabe von PowerShell-Cmdlets speichern


    Tags:

    Powershell-LogoGelegentlich besteht in einer PowerShell-Pipeline die Notwendigkeit, die Ausgabe eines Cmdlets aufzubewahren, um diese Daten in einem nachfolgenden Kommando zu verwenden. Für diesen Zweck verfügen alle Cmdlets über die Parameter OutVariable und PipelineVariable. Letztere ist nur temporär verfügbar.

    Eine gängige Anforderung in einer PowerShell-Pipeline besteht darin, dass man ein Zwischenergebnis in eine Datei umleiten und zusätzlich an ein weiteres Cmdlet durchreichen möchte. In diesem Fall teilt das Cmdlet Tee-Object den Datenfluss auf zwei Output-Kanäle.

    Wenn man jedoch das Zwischenergebnis im übernächsten Kommando oder nach dem Durchlaufen der Pipeline verwenden möchte, dann ist Tee-Object dafür nicht geeignet. Man könnte sich ein Szenario so vorstellen, dass man in der Pipeline

    Befehl_1 | Befehl_2 | Befehl_3 | Befehl_4

    die Ausgabe von Befehl_2 in Befehl_4 verarbeiten will.

    Cmdlet-Ausgabe in OutVariable speichern

    Die Lösung besteht im allgemeinen Parameter OutVariable.

    Befehl_1 | Befehl_2 -OutVariable MyVar | Befehl_3 | Befehl_4 mit MyVar

    Wie man sieht, verzichtet man beim Wert für den Parameter OutVariable (Alias "ov") auf das führende $-Zeichen im Variablen­namen. Die in diesem Musteraufruf eingesetzte Variable $MyVar besteht auch nach dem Ende der Pipeline.

    Das folgende Beispiel ermittelt alle PDF-Dateien im aktuellen Verzeichnis, filtert sie nach Größe und gibt deren Namen aus. Wenn man im Anschluss daran die aufsummierte Größe der Dateien anzeigen möchte, dann müsste man die ersten beiden Kommandos der Pipeline erneut aufrufen.

    Wenn man jedoch das Ergebnis von Where-Object in einer Variablen speichert, dann kann man sich diesen Aufwand sparen:

    Get-ChildItem *.pdf | where Length -lt 100000 -OutVariable PDF |
    select name

    $PDF | measure -Property Length -sum |
    select @{n="Dateien";e={$_.count}}, `
    @{n="Größe in MB";e={[math]::round($_.sum / 1MB, 2)}}

    Output der Pipeline nach dem zweiten Befehl zwischenspeichern und zur Berechnung der Dateigrößen verwenden

    In $PDF befindet sich die komplette Ausgabe von Get-ChildItem für alle Dateien, die größer als 100K Byte sind. Die Variable ist vom .NET-Datentyp ArrayList, wie man mit

    $PDF.GetType()

    leicht feststellen kann.

    Auf die einzelnen Elemente kann man über den Index zugreifen, also entweder in der Form

    $PDF[0]

    oder

    $PDF.Item(0)

    Nachdem OutVariable immer vom Typ ArrayList ist, eignet sich diese Variable nicht als genereller Ersatz für eine Zuweisung, weil dies zu unerwarteten Nebeneffekten führen kann. Man sollte also zum Beispiel

    $cim = New-CimSession -ComputerName server1 -Credential contoso\user

    nicht durch

    New-CimSession -ComputerName server1 -Credential contoso\user -ov cim

    ersetzen, nur weil man sich dadurch etwas Tipparbeit ersparen kann.

    PipelineVariable

    Der Parameter PipelineVariable (Alias "pv") erfüllt im Wesentlichen den gleichen Zweck wie OutVariable, hat aber einen eingeschränkten Gültigkeitsbereich. Sie ist, wie der Name vermuten lässt, nur innerhalb der Pipeline verfügbar.

    Zum anderen ist sie nicht vom Typ ArrayList, sondern erhält den nativen Datentyp des Rückgabewerts eines Cmdlets.

    Im folgenden Beispiel sollen der Nachname und die Gruppen­mitglied­schaften eines AD-Users ausgegeben werden.

    Nach der Ausführung von Select-Object mit dem Parameter ExpandProperty enthält die Pipeline nur mehr die Liste der AD-Gruppen als Strings, das Ergebnis von Get-ADUser ist zu diesem Zeitpunkt für eine weitere Verarbeitung nicht mehr verfügbar.

    Hier hilft der Einsatz von PipelineVariable:

    Get-ADUser -Filter 'name -like "b*"' -Properties * -pv u |
    select -ExpandProperty MemberOf |
    select @{n="Nachname";e={ $u.surname }}, @{n="Gruppen";e={ $_ }}

    Die Variable $u enthält dann das Array mit den ADUSer-Objekten. Auf sie kann im abschließenden Aufruf von Select-Object zurückgreifen.

    Verwendung von PipelineVariable zur Ausgabe der Gruppenmitgliedschaften von AD-Benutzern

    Zusammenfassung

    Damit man im Datenstrom durch eine PowerShell-Pipeline auf ein vorheriges Zwischen­ergebnis zurückgreifen kann, unterstützen alle Cmdlets die Parameter OutVariable und PipelineVariable, um ihre Ausgabe in einer Variablen zu speichern. Beiden übergibt man einen Namen ohne das führende $-Zeichen.

    OutVariable ist auch noch nach der Beendigung der Pipeline verfügbar und hat immer den Datentyp ArrayList. Der Gültigkeits­bereich von PipelineVariable beschränkt sich hingegen auf die Pipeline und die Variable behält den Datentyp des Cmdlet-Ergebnisses.

    Täglich Know-how für IT-Pros mit unserem Newsletter

    Wir ver­wenden Ihre Mail-Adresse nur für den Ver­sand der News­letter.
    Es erfolgt keine per­sonen­be­zogene Auswertung.

    Bild von Wolfgang Sommergut

    Wolfgang Sommergut hat lang­jährige Erfahrung als Fach­autor, Berater und Kon­ferenz­sprecher zu ver­schie­denen Themen der IT. Da­ne­ben war er als System­ad­mi­ni­stra­tor und Con­sultant tätig.
    // Kontakt: E-Mail, XING, LinkedIn //

    Verwandte Beiträge

    Weitere Links