Wie kann ich in PowerShell eine vorformatierte Ausgabe analysieren?

Wie kann ich in PowerShell eine vorformatierte Ausgabe analysieren?

Gibt es vorhandene Tools, um textbasierte Ausgaben an ein dynamisches Objekt weiterzuleiten, das als Spalten abgefragt werden kann?

Genauer gesagt, ich berufe mich auf...

query session /server:MYSERVER

.. was ausgibt ..

SESSIONNAME       USERNAME                 ID  STATE   TYPE        DEVICE 
services                                    0  Disc                        
console           Jon                       1  Active  

Dies ist meine erste Aufgabe in einer DevOps-Rolle, auf diese Ausgabe basierend auf den Bedingungen der Spalten zu reagieren, aber nach mehreren Versuchen, eine Weiterleitung in foreach usw. durchzuführen, wurde mir klar, dass es sich alles nur um mehrere Zeilen mit Zeichenfolgen handelt.

Ich hatte auf so etwas gehofft wie …

query session /server:MYSERVER | foreach `
{ `
    if ($_.Username -eq "Jon") `
    {`
        custom-action $_.ID `
    } `
}

(Beachten Sie, dass ich den Benutzernamen nicht unbedingt auswerten muss, bzw. nicht nur den Benutzernamen, ich tue dies nur in diesem Beispiel.)

Offensichtlich wird das nicht funktionieren, weil dies …

query session /server:192.168.1.103 | foreach { echo $_.GetType() }

.. gibt dies aus ..

IsPublic IsSerial Name                                     BaseType                                                    
-------- -------- ----                                     --------                                                    
True     True     String                                   System.Object                                               
True     True     String                                   System.Object                                               
True     True     String                                   System.Object     

Die einzige Lösung, die ich gefunden habe, ist das manuelle Extrahieren der Spalten mit String.Substring(). Ich hatte gehofft, dass es PowerShell-Tools gibt, die dies automatisieren.

[[Dies ist ein Beispiel,]], aber einige Spalten sind leer und die Spalten mit fester Breite haben untereinander nicht die gleiche Breite, sodass die Analyse viel manueller wäre als die Beispiele dort. Ich hatte gehofft, dass Powershell-Versionsupdates vielleicht bessere Tools bieten?

Verwenden von Windows Server 2012 R2 (mit PowerShell 4).

Antwort1

Da ist nichts eingebaut.

Es sollte jedoch nicht zu schwierig sein, einen Helfer zu erstellen (natürlich in einem Modul zur einfachen Wiederverwendung), der eine Definition jeder Spalte (z. B. Name, Startposition, Länge, Typ usw. oder vielleicht alternative Kriterien zum Trennen der Spalten, wenn die Längen nicht im Voraus bestimmt werden können) übernimmt und ein benutzerdefiniertes Objekt erstellt.

Antwort2

Viele dieser Dienstprogramme aus der Zeit vor PowerShell fragen verschiedene zugrunde liegende Windows-APIs ab, beispielsweise WMI. Bevor ich mich mit der Textanalyse befasse, würde ich versuchen, herauszufinden, woher das Dienstprogramm seine Informationen bezieht, und dort beginnen. In Ihrem speziellen Fall würde es mich nicht überraschen, wenn es tatsächlich die WMI-Klasse Win32_LogonSession abfragt, die Sie mit PowerShell problemlos aufzählen und richtig formatierte Objekte zurückerhalten können. Dieser Ansatz funktioniert möglicherweise nicht in allen Situationen, aber er wäre zumindest ein guter Ausgangspunkt.

$users = get-wmiobject -query "Select * from Win32_LogonSession"

Nach ein bisschen Googeln scheint dies eine vielversprechende Funktion für das zu sein, was Sie benötigen: Funktion „get-loggedonuser“

Antwort3

Dies ist ein Kommentar zu Richards Antwort.

Das ist, was mir eingefallen ist. Man würde foreach{} auf alle Zeilen anwenden (außer auf die erste Zeile, die $head ist) und an diese Funktion übergeben.

Function ParseFixedWidthCols($head,$line) {
    $colnamematches = $head | select-string "(\s*\w+\b\s*)" -allmatches | foreach { $_.matches }
    $cols = @()
    for ($ci=0; $ci -lt $colnamematches.Count; $ci++) {
        $col = $colnamematches[$ci].Value
        $cols += $col
    }
    $col = $cols[0]
    $ret = New-Object PSObject
    $cc = 0
    for ($ci=0; $ci -lt $cols.Count; $ci++) {
        $value = $line.Substring($cc, $cols[$ci].Length)
        $ret | Add-Member -MemberType NoteProperty -name $cols[$ci].Trim() -value $value.Trim()
        $cc += $cols[$ci].Length
    }
    return ret;
}

verwandte Informationen