Windows PowerShell Filtern und Formatieren von Daten

Don Jones

Es besteht kein Zweifel daran, dass Windows PowerShell ohne großen Arbeitsaufwand Ihrerseits viele wertvolle Informationen liefern kann. Betrachten Sie beispielsweise das einfache Cmdlet „Get-WMIObject“. Mit diesem Cmdlet können Sie eine Liste der Dienste auf dem lokalen Computer abrufen. Die Standardansicht, die den Status, den Namen und den Startmodus

der ausgeführten Dienste enthält, ist im Prinzip eine Befehlszeilenansicht der Dienste. Mit Windows PowerShell™ gelangen Sie jedoch leichter an diese Daten.

Es gibt aber neben den Angaben in der Standardansicht noch viel nützlichere Informationen zu Diensten. Probieren Sie einmal den folgenden Befehl aus:

$s = get-wmiobject win32_service
$s[0] | gm

Die erste Zeile des Befehls gibt eine Sammlung aller Dienste zurück (oder eher aller Instanzen der Win32_Service-Klasse aus Windows® Management Instrumentation oder WMI) und speichert sie in der Variable $s. Die zweite Zeile leitet den ersten Dienst aus dieser Sammlung (Ordnungszahl Null, in eckigen Klammern) zum Cmdlet „Get-Member“ weiter, abgekürzt mit dem Alias „gm“. Die resultierende Datenausgabe zeigt alle für diesen Datentyp verfügbaren Eigenschaften und Methoden. Hier soll die Win32_Service-Klasse in WMI anstelle des integrierten Cmdlet „Get-Service“ in Windows PowerShell verwendet werden, weil WMI mehr Daten offen legt als das Microsoft® .NET-Objekt „Service-Controller“, beispielsweise die Eigenschaft „Start­Name“. Diese Eigenschaft gibt den Namen des Benutzerkontos zurück, unter dem der Dienst ausgeführt wird. So können Sie den Namen einer einzelnen Instanz prüfen (z. B. der ersten Instanz):

PS C:\> $s[0].StartName
LocalSystem

Die Referenzierung der Dienste über ihre Ordnungszahl innerhalb der Sammlung ist allerdings nicht sehr sinnvoll, weil die Dienste in keiner besonderen Reihenfolge aufgeführt sind. (In der Regel sind sie alphabetisch sortiert, jedoch nicht immer.) Mit Blick auf die Verwaltung wäre wohl eine Liste aller Dienste mit dem zugehörigen Benutzerkonto für die Anmeldung am interessantesten. Dies wäre beispielsweise für eine Konformitätsprüfung von Nutzen. Betrachten wir also als Erstes die standardmäßige Datenausgabe von WMI. In diesem Beispiel soll der kürzere Alias von „Get-WMIObject“ verwendet werden, also „gwmi“ (siehe Abbildung 1).

Figure 1 Verwenden von „gwmi“

PS C:\> gwmi win32_service

ExitCode  : 0
Name      : AcrSch2Svc
ProcessId : 1712
StartMode : Auto
State     : Running
Status    : OK

ExitCode  : 1077
Name      : Adobe LM Service
ProcessId : 0
StartMode : Manual
State     : Stopped
Status    : OK

Schon an diesem Beispiel sehen Sie, dass die Ausgabe nicht sonderlich als Verwaltungsbericht geeignet ist. Sie möchten den Namen des Diensts erfahren und auch den „StartName“, also das Benutzerkonto, unter dem der Dienst ausgeführt wird. Weiterhin soll der Bericht übersichtlicher als in dieser etwas umständlichen Liste dargestellt werden. Genau hier kommen die beachtlichen Formatierungs- und Datenfilterungs-Cmdlets von Windows PowerShell ins Spiel.

Alle Daten, die Sie brauchen

Als Erstes sollen die Daten aus „Get-WMIObject“ so gefiltert werden, dass nur die für Sie interessanten Eigenschaften angezeigt werden. Dies lässt sich am besten mit dem Windows PowerShell-Cmdlet „Select-Object“ oder dessen einfachem Alias „select“ erreichen. „Select“ übernimmt eine Sammlung von Objekten (beispielsweise die von „Get-WMIObject“ zurückgegebene Sammlung) und zeigt dann nur die gewünschten Eigenschaften dieser Objekte an. Sie können also die Ausgabe von „gwmi“ an „select“ weiterleiten und dann die beiden gesuchten Eigenschaften auswählen. Abbildung 2 zeigt die Ergebnisse: Die Eigenschaften „Name“ und „StartName“ sind ordentlich in einer Tabelle dargestellt.

Abbildung 2 Abrufen der Eigenschaften „Name“ und „StartName“ in einer Tabelle

Abbildung 2** Abrufen der Eigenschaften „Name“ und „StartName“ in einer Tabelle **(Klicken Sie zum Vergrößern auf das Bild)

Zum Zweck einer Konformitätsprüfung enthält dieser Bericht aber immer noch zu viele Informationen. Da ein Teil der Dienste deaktiviert ist, ist es für den Bericht belanglos, welches Benutzerkonto diese deaktivierten Dienste theoretisch verwenden. Daher sollen alle Dienste herausgefiltert werden, die den Starttyp „Deaktiviert“ aufweisen. Dies ist die Eigenschaft „StartMode“ der Win32_Service-Klasse.

Bei Windows PowerShell erfolgt die Objektfilterung über das Cmdlet „Where-Object“ bzw. über den kürzeren Alias „where“. Das Cmdlet „where“ übernimmt eine Sammlung von Eingabeobjekten und führt für jedes Objekt einen Skriptblock aus, mit dem ermittelt wird, ob das jeweilige Objekt gemäß der definierten Kriterien in der Ausgabe des Cmdlet aufgeführt werden soll oder nicht. Alle Objekte, die die Kriterien erfüllen, geben den Vergleichswert „Wahr“ zurück und werden in die Ausgabe aufgenommen; Objekte mit dem Wert „Falsch“ fallen entsprechend heraus.

Damit haben Sie festgelegt, dass nur solche Objekte berücksichtigt werden sollen, bei denen die Eigenschaft „StartMode“ den Wert „Deaktiviert“ aufweist. In Windows PowerShell ergibt sich der folgende Ausdruck:

$object.StartMode –eq “Disabled”

„$object“ ist dabei nur ein Beispiel. An dieser Stelle wird kein Skript verfasst, sodass auch keine Variable mit der Bezeichnung „$object“ vorliegt. Innerhalb des Skriptblocks, der durch das Cmdlet „where“ verwendet wird, kommt allerdings eine besonderen Variable mit der Bezeichnung „$_“ zum Einsatz. Diese Variable steht für das Objekt, das derzeit durch das Cmdlet ausgewertet wird. Der „where“-Skriptblock könnte daher wie folgt aufgebaut sein:

$_.StartMode –eq “Disabled”

Dies lässt sich mühelos testen:

PS C:\> gwmi win32_service | where 
{$_.StartMode -eq “Disabled”}

ExitCode  : 1077
Name      : Alerter
ProcessId : 0
StartMode : Disabled
State     : Stopped
Status    : OK

Bei diesem Schnelltest erfolgt die Ausgabe natürlich wieder im normalen Listenstil. Aus Platzgründen wird der Skriptblock für unsere Zwecke auf einen einzigen Dienst beschränkt. Dennoch ist erkennbar, dass die Ausgabe umgekehrt gestaltet ist. Hier sind die deaktivierten Dienste nicht ausgeschlossen, sondern eingeschlossen. Der Grund dafür liegt darin, dass der Skriptblock umgekehrt formuliert ist: Es sollen alle Dienste berücksichtigt werden, die nicht über den Wert „Deaktiviert“ für „StartMode“ verfügen. Dies zeigt die folgende Änderung am Beispiel:

PS C:\> gwmi win32_service | where 
{$_.StartMode -ne “Disabled”}

ExitCode  : 0
Name      : AcrSch2Svc
ProcessId : 1712
StartMode : Auto
State     : Running
Status    : OK

Schon besser! Nun enthält die Ausgabe nur noch die für Sie interessanten Dienste. Leiten Sie die Ausgabe also erneut an „select“ weiter und geben Sie nur die gewünschten Eigenschaften an:

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | select name,startname

Diese Weiterleitung der Daten von einem Cmdlet zu einem anderen und dann noch zu einem dritten veranschaulicht die Leistung von Windows PowerShell. Sie haben immer noch kein Skript geschrieben, und doch haben Sie eine umfangreiche Datenmenge so gefiltert, dass Sie genau die gewünschte Ausgabe erhalten.

Das richtige Aussehen

Denken Sie daran, dass „select“ nach wie vor eine bunte Anhäufung von Objekten zurückgibt. Wenn Sie eine ordentlich formatierte Tabelle mit Windows PowerShell abrufen, ist diese Tabelle im Grunde genommen nur die PowerShell.exe-Darstellung dieser Objekte. Anders gesagt: Windows PowerShell „weiß“, dass ich als Mensch die Objekte nicht sehen kann, weshalb die Objekte als Text wiedergegeben werden. In diesem Fall werden die Objekte in Form einer Tabelle mit je einer Spalte für de einzelnen Eigenschaften wiedergegeben (siehe Abbildung 2).

Für Prüfzwecke könnte dies durchaus reichen. Das hängt ganz von den Umständen ab. Jeder Benutzer hat ganz eigene Bedürfnisse, und Windows PowerShell kann Ihre speziellen Anforderungen nicht ohne weiteres vorhersehen. Stattdessen erhalten Sie geeignete Tools, mit denen Sie die Ausgabe ganz nach Wunsch formatieren können. Die vier integrierten Cmdlets („Format-List“, „Format-Custom“, „Format-Table“ und „Format-Wide“) übernehmen eine Sammlung von Objekten (z. B. die von „select“ zurückgegebene Sammlung) und formatieren die Objekte auf unterschiedliche Weise. „Format-Table“ entspricht dabei der Formatierung, die bereits für die Ausgabe von „select“ zum Einsatz kam. Probieren Sie nun „Format-List“ aus:

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | format-list

Das Ergebnis dürfte ähnlich wie dieses Beispiel aufgebaut sein:

name      : AcrSch2Svc
startname : LocalSystem

name      : Adobe LM Service
startname : LocalSystem

Mit dem Cmdlet „Format-Wide“ erhalten Sie eine mehrspaltige Liste, in der (standardmäßig) die erste Eigenschaft der einzelnen Objekte aufgeführt wird. Sehen Sie sich z. B. diese Zeile an:

gwmi win32_service | where {$_.StartMode -ne “Disabled”} |
 select name,startname | format-wide

Es wird eine Liste der Dienstnamen zurückgegeben, die für Ihre Zwecke nicht geeignet ist. In der Ausgabe fehlt die Angabe für „StartName“ (siehe Abbildung 3), eine wichtige Information, die für einen Prüfbericht benötigt wird.

Abbildung 3 „StartName“ fehlt in der Ausgabe des Cmdlet „Format-Wide“

Abbildung 3** „StartName“ fehlt in der Ausgabe des Cmdlet „Format-Wide“ **(Klicken Sie zum Vergrößern auf das Bild)

Dieses Beispiel beschränkt sich lediglich auf zwei Eigenschaften, sodass die Option „Format-Table“ oder „Format-List“ zu annehmbaren Ergebnissen führen müsste. Die meisten Wirtschaftsprüfer würden diese Informationen allerdings nicht gern am Bildschirm lesen. Die Ausgabe in einer Datei wäre wohl besser.

Exportieren von Daten

Wie sollten die Daten also für den Wirtschaftsprüfer dargestellt werden? Im Normalfall reicht die Ausgabe einer Liste der Dienste und Anmeldenamen in eine CSV-Datei (mit Trennzeichen zwischen den Daten), weil diese Datei problemlos in Microsoft Excel® geöffnet werden kann. Zum Erstellen einer CSV-Datei leiten Sie einfach die Ausgabe an das Windows PowerShell-Cmdlet „Export-CSV“ weiter:

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | export-csv c:\services.csv

Heutzutage erscheinen CSV-Dateien oft ein wenig antiquiert. Alternativ ließen sich die Daten für den Wirtschaftsprüfer als Webseite auf einem Intranetserver darstellen. Konvertieren Sie hierzu die Ausgabe als Erstes mit dem Cmdlet „ConvertTo-HTML“ in das HTML-Format:

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | convertto-html

HTML-Rohdaten sind nur schwer lesbar. Die Ausgabe muss also in eine Datei geschrieben werden:

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | convertto-html | out-file c:\services.html

Das Ergebnis (siehe Abbildung 4) ist eine gut formatierte HTML-Seite, die Sie ohne weitere Änderungen auf einem Webserver bereitstellen können.

Abbildung 4 Ausgabe als gut formatierte HTML-Seite

Abbildung 4** Ausgabe als gut formatierte HTML-Seite **(Klicken Sie zum Vergrößern auf das Bild)

Nur die (relevanten) Tatsachen

Windows PowerShell eröffnet den raschen Zugriff auf umfangreiche Verwaltungsdaten. Im Rohzustand sind diese Daten jedoch geschäftlich nicht nutzbar.

Wenn Sie die Daten filtern (mit „where“), die gewünschten Objekteigenschaften auswählen (mit „select“) und dann eine geeignete Formatierungsoption anwenden (z. B. „Format-Table“ oder „Format-List“), verwandeln Sie diese Verwaltungsdaten im Handumdrehen in aussagekräftige Informationen. Durch anschließendes Exportieren in ein leicht weiterzugebendes Dateiformat können Sie diese nützlichen Daten dann anderen Mitarbeitern in Ihrem Unternehmen zur Verfügung stellen.

Don Jones ist Direktor für Projekte und Dienste bei SAPIEN Technologies und Mitautor von Windows PowerShell: TFM (SAPIEN Presse). Sie erreichen Don Jones über seine Website unter www.ScriptingAnswers.com.

© 2008 Microsoft Corporation und CMP Media, LLC. Alle Rechte vorbehalten. Die nicht genehmigte teilweise oder vollständige Vervielfältigung ist nicht zulässig.