Windows PowerShellArbeiten ohne Skript

Don Jones

Wenn ich mich über Windows PowerShell unterhalte – ob auf einer Konferenz, in der öffentlichen Windows PowerShell-Newsgroup oder sogar auf meiner Website – begegne ich stets Administratoren, die mir sagen, dass sie damit „warten“ werden, Windows PowerShell kennenzulernen. Warum? Dies ist der häufigste Grund, den sie dafür angeben:

„Im Moment habe ich einfach keine Zeit zu lernen, wie ein Skript erstellt wird.“

Dies dürfte die allgemeine Stimmung ausdrücken. Administratoren sind vielbeschäftigt und haben nicht gerade viel freie Zeit zum Erlernen neuer Technologien. Doch wir müssen immer vorausschauen und uns mit neuer Software wie Windows Vista®, Windows Server® 2008 und Exchange Server 2007 vertraut machen, sodass wir die Technologien kennen, die über den Erfolg unserer Arbeit entscheiden. Windows PowerShell™ stellt einen großen Teil dieser Technologien dar.

Ein anderer Grund, der von Administratoren häufig dafür angeführt wird, warum sie es aufschieben, die Skripterstellung in Windows PowerShell zu lernen, ist die „Befürchtung zum Programmierer zu werden“, wie ein Kollege dies einmal ausdrückte. Das ist etwas, wobei ich Ihnen helfen kann. Es wird Sie vielleicht überraschen, doch Sie können mit Windows PowerShell Erstaunliches bewerkstelligen, ohne eine einzige Zeile Code zu schreiben.

Vorbereitung auf die Pipeline

Ich habe bereits einen Artikel über die äußerst flexible und leistungsfähige objektorientierte Pipeline geschrieben, die von Windows PowerShell verwendet wird. (Auch wenn Sie aufgrund der Bezeichnung „objektorientiert“ befürchten, dass ich hier auf Programmierung zusteuere, haben Sie bitte Geduld.) Eines der Merkmale, die mir an der Pipeline am meisten zusagen, ist die Art und Weise, wie sie interaktiv eingesetzt werden kann. Sie erhalten unmittelbare Ergebnisse, und können diese leicht optimieren, sodass Sie genau das erhalten, was Sie im Auge hatten. Nehmen Sie zum Beispiel an, dass ich die Bestandsaufnahme des freien Speicherplatzes für mehrere Remotecomputer abrufen will. Angenommen, die Namen der Computer sind in der Textdatei „C:\Computers.txt“ aufgelistet. Es handelt sich einfach um eine Nur-Text-Datei mit einem Computernamen pro Zeile, nichts Kompliziertes wie etwa eine Datenbank.

Als Erstes überprüfe ich, ob ich diese Informationen von meinem lokalen Computer abrufen kann. Denn wenn dies mit einem Computer funktioniert, dann dürfte es relativ einfach auch mit mehreren Computern klappen. Noch einmal zur Erinnerung: Hierbei soll keinerlei Skripterstellung verwendet werden. Der gesamte Arbeitsgang erfolgt interaktiv in der Shell, die Ergebnisse werden direkt nach Drücken der Eingabetaste ausgegeben.

Hier ist ein Tipp zu dieser Art von Aufgabe. Wenn Sie von Remotecomputern Bestandsverwaltungsinformationen abrufen wollen, werden Sie wahrscheinlich Windows® Management Instrumentation (WMI) verwenden. Nehmen Sie jetzt für dieses Beispiel an, dass ich keinerlei über die Verwendung von WMI hinausgehenden Kenntnisse besitze. Also gehe ich zu Live Search und gebe „Windows WMI freier Speicherplatz“ als Suchbegriff ein. Es werden mehrere Ergebnisse angezeigt, deren Auszüge den Ausdruck „Win32_LogicalDisk“ enthalten. Für mich sieht dies nach einer WMI-Klasse aus, und es dürfte diejenige sein, die ich suche. Ich klicke gar nicht erst auf die Suchergebnisse. Stattdessen gebe ich als neuen Suchbegriff „Win32_LogicalDisk“ ein, und das oberste Suchergebnis verweist auf eine Win32_LogicalDisk-Dokumentationsseite auf der MSDN®-Site (msdn2.microsoft.com/aa394173.aspx). Also gehe ich zu dieser Seite und sehe, dass eine der Eigenschaften dieser Klasse „FreeSpace“ heißt, was sich sehr vielversprechend anhört.

Finden eines Cmdlet

Im nächsten Schritt muss ich ein Cmdlet finden, das für mich die Eigenschaften einer WMI-Klasse abruft. Die fantastischen integrierten Selbstermittlungsfeatures stellen einen der bemerkenswerten Aspekte von Windows PowerShell dar. Das heißt, die Shell kann Ihnen helfen, mehr über ihre eigenen Merkmale herauszufinden. Also gebe ich „Help *wmi*“ ein, um festzustellen, inwieweit die Shell mit WMI zusammenarbeiten kann. Das Ergebnis sind der Gwmi-Alias und das Cmdlet „Get-WMIObject“, auf das dieser verweist (siehe Abbildung 1). Im Grunde gibt es zwei Möglichkeiten, auf die gleiche Funktionalität zuzugreifen. Die Entscheidung, welche davon ich verwenden muss, fällt also nicht schwer. Da sie das Gleiche bewirken und die Eingabe von „Gwmi“ kürzer ist, verwende ich das:

Abbildung 1 Was die Shell über die Arbeit mit WMI weiß

Abbildung 1** Was die Shell über die Arbeit mit WMI weiß **(Klicken Sie zum Vergrößern auf das Bild)

PS C:\> gwmi win32_logicaldisk

Bei Windows PowerShell wird nicht zwischen Groß- und Kleinschreibung unterschieden. Administratoren haben schließlich keine Zeit für umständliche Details wie das Drücken der Umschalttaste.

Die Ergebnisse dieses Befehls, die in Abbildung 2 gezeigt werden, umfassen meine fünf lokalen Laufwerke und ihre FreeSpace-Eigenschaften, die offenbar in Byte aufgelistet werden. Außerdem wird die DriveType-Eigenschaft für jedes dieser Laufwerke aufgelistet, auf meinem Computer sehe ich die Werte 2, 3 und 5.

Abbildung 2 Alle lokalen Laufwerke und deren FreeSpace-Eigenschaften

Abbildung 2** Alle lokalen Laufwerke und deren FreeSpace-Eigenschaften **(Klicken Sie zum Vergrößern auf das Bild)

Cmdlet des Monats

Sie haben möglicherweise bereits mit Get-Content den Inhalt einer Textdatei abgerufen. Es behandelt jede Zeile der Datei als [string]-Objekt und leitet die Objekte an die Pipeline weiter, damit sie von anderen Cmdlets bearbeitet werden können. Get-Content weist jedoch eine Reihe von Optionen auf, durch die es flexibler wird: Der Parameter „–readCount“ ermöglicht Ihnen beispielsweise die Angabe, wie viele [string]-Objekte gleichzeitig an die Pipeline weitergeleitet werden (in der Standardeinstellung sind dies alle), während der Parameter „–totalCount“ die Gesamtanzahl der Zeilen steuert, die von der Datei gelesen werden. Beide Parameter sind für die Arbeit mit sehr großen Dateien nützlich, bei denen Sie aus Leistungsgründen möglicherweise nicht die ganze Datei sofort verarbeiten möchten.

Hier ist ein weiterer nützlicher Parameter: –encoding ermöglicht, dass eine große Vielfalt von Dateicodierungstypen, einschließlich Unicode, ASCII, UTF7, UTF8 und viele andere, korrekt gelesen werden. Um eine vollständige Liste unterstützter Codierungstypen anzuzeigen, führen Sie „help gc“ aus (gc ist ein Alias von Get-Content).

Optimieren der Daten

An diesem Punkt stehe ich vor zwei Problemen. Erstens möchte ich nur Angaben zur Eigenschaft „FreeSpace“. Die anderen Eigenschaften interessieren mich nicht. Zweitens will ich nichts über freien Speicherplatz auf optischen Laufwerken, Wechsellaufwerken und Netzwerklaufwerken wissen. Mich interessieren nur lokale Festplatten. Vielleicht kann die DriveType-Eigenschaft mir bei dieser Unterscheidung helfen. Ich gehe zurück zu meinem Webbrowser und sehe, dass die Dokumentation eine Tabelle enthält, in der erklärt wird, was die verschiedenen DriveType-Werte bedeuten. Mich interessieren nur diejenigen mit DriveType 3, wodurch angezeigt wird, dass es sich beim Laufwerk um eine lokale Festplatte handelt. Da ich dies noch nie zuvor ausgeführt habe, möchte ich sehen, ob der Gwmi-Befehl eine Art Filterung vornehmen kann. Durch Ausführen von Help Gwmi –full erhalte ich Einzelheiten über die Funktionsweise des Befehls, einschließlich einiger Beispiele. Ich finde einen Parameter, der nützlich aussieht ( –filter), und beschließe, versuchsweise Folgendes auszuführen:

gwmi win32_logicaldisk -filter "drivetype = 3"

Es hat funktioniert! Meine Laufwerksliste enthält jetzt nur lokale Festplatten. Damit ist das zweite Problem gelöst. Jetzt muss ich das erste Problem lösen und all die Eigenschaften loswerden, die mich nicht interessieren.

Ich führe Get-Command aus, um alle Windows PowerShell-Cmdlets aufzulisten, und schließlich stoße ich auf Select-Object. Die Beschreibung besagt, dass damit die angegebenen Eigenschaften eines Objekts oder Objektsatzes ausgewählt werden. Also versuche ich Folgendes:

gwmi win32_logicaldisk -filter "drivetype = 3" | select freespace

Durch das Leiten der Ergebnisse von Gwmi an Select (dem Alias von Select-Object) kann ich genau die Eigenschaft abrufen, die ich will. Doch diese Ergebnisse sind nicht so gut, da nur noch eine Liste von Nummern bleibt und ich nicht mehr weiß, welches Laufwerk zu welcher Freispeicherplatzliste gehört. Deshalb gehe ich zurück zur Dokumentation und sehe, dass die DeviceID-Eigenschaft den Laufwerkbuchstaben enthält. Ich überarbeite schnell meinen Befehl und versuche es erneut:

gwmi win32_logicaldisk -filter "drivetype = 3" | select deviceid,freespace

Perfekt! Da nur zwei Eigenschaften aufgelistet werden, kann die Shell die Informationen in eine übersichtliche Tabelle eintragen. (Nächsten Monat werde ich erläutern, wann Windows PowerShell Listen und wann Tabellen verwendet.)

Berechnen

Ich habe die Informationen zu freiem Speicherplatz abgerufen, doch sie sind in Byte angegeben und nicht so nützlich wie Megabyte oder Gigabyte. Ggf. interessiert mich die FreeSpace-Eigenschaft selbst gar nicht, sondern ein Wert, der aus dieser berechnet wird. Das Cmdlet „ForEach-Object“ (oder einer seiner vielen Aliase, wie z. B. „%“) kann hier weiterhelfen. Dieses Cmdlet ermöglicht die Verwendung einer besonderen Variablen, $_, für den Verweis auf den aktuellen logischen Datenträger. Außerdem ermöglicht es den Zugriff auf die Eigenschaften der einzelnen Datenträger und das Anstellen einiger Berechnungen. Hier sehen Sie meinen überarbeiteten Befehl:

gwmi win32_logicaldisk -filter "drivetype = 3" | % { $_.deviceid; $_.freespace/1GB }

Ich habe Select entfernt und durch den Alias von ForEach-Object (%) ersetzt. Das Cmdlet benötigt von mir nur die Information, was es mit den einzelnen Win32_LogicalDisk, die es abruft, machen soll. Meine Anweisung lautet, dass es die DeviceID-Eigenschaft abrufen und die FreeSpace-Eigenschaft durch ein Gigabyte teilen soll – Windows PowerShell „weiß“, was ein KB, MB und GB sind – sodass meine Ausgabe in Gigabyte angezeigt wird.

Anwenden auf viele Computer

Der Befehl funktioniert nun mit einem Computer, und es ist Zeit, ihn auf mehrere anzuwenden. Ich weiß, wie ich den Inhalt einer Textdatei abrufe. Wie zu MS-DOS®-Zeiten wird der Befehl „Type“ verwendet. In Windows PowerShell ist dieser ein Alias von Get-Content:

Type c:\computers.txt

Ich habe Folgendes vor: Ich möchte für jeden einzelnen Computer den WMI-Befehl durchführen, den ich bereits ausgearbeitet habe. Bei „für jeden einzelnen“ denken Sie sicher an ein Cmdlet, insbesondere an ForEach-Object. Lange Rede kurzer Sinn, dies ist der endgültige Befehl:

type c:\computers.txt | % { $_; 
gwmi –computername $_ win32_logicaldisk -filter "drivetype=3" | % { $_.deviceid; $_.freespace/1GB} }

Furchterregend, nicht wahr? Dank meiner ausschließlichen Verwendung von Aliasen anstatt Cmdlet-Namen, ist er schwierig zu lesen. Er ist jedoch relativ leicht zu entschlüsseln, wenn Sie immer nur einen Teil betrachten.

  • Ich starte durch „Kategorisieren“ des Inhalts meiner Textdatei.
  • Ich leite den Inhalt zu ForEach-Object.
  • ForEach-Object gibt mithilfe der Variablen „$_“ das aktuelle Element aus. (Das ist der aktuelle Computername.)
  • ForEach-Object führt dann meinen WMI-Befehl aus, der einen anderen ForEach-Object-Aufruf umfasst.

Es mag hilfreich sein, die Aliase durch die Cmdlets zu ersetzen. Hier ist der gleiche Befehl, aber diesmal habe ich die Cmdlets ausgeschrieben und den Befehl in einzelne Zeilen unterteilt, damit Sie die Abschnitte leichter sehen können:

Get-Content C:\Computers.txt | 
ForEach-Object { 
 $_; Get-WMIObject –computername $_ 
Win32_LogicalDisk -filter "DriveType=3" | 
 ForEach-Object { 
 $_.DeviceID; $_.FreeSpace/1GB
 }
}

Das nicht sehr ansprechende jedoch funktionsfähige Ergebnis ist in Abbildung 3 zu sehen.

Abbildung 3 Endergebnis

Abbildung 3** Endergebnis **(Klicken Sie zum Vergrößern auf das Bild)

Keine Skripterstellung erforderlich

Diese Anleitung veranschaulicht, dass Sie Windows PowerShell ohne jegliche Skripterstellung verwenden können. Mit nur wenigen Befehlen wie diesem hier und ein wenig Forschungsarbeit in Windows PowerShell selbst können Sie einige der Elemente finden, die Sie für die Erledigung Ihrer jeweiligen Aufgabe benötigen.

Windows PowerShell wird nicht mehr von der Bildfläche verschwinden. Warum also nicht jetzt anfangen, ihre Verwendung zu erlernen? Sie werden sich vielleicht sogar wundern, wie Sie so lange ohne Windows PowerShell ausgekommen sind. Auf jeden Fall sollten Sie sich nicht von dem Gespenst der Skripterstellung davon abhalten lassen, sich gleich in die Materie einzuarbeiten.

Don Jones ist der führende Scripting-Guru bei SAPIEN Technologies und Ausbilder für ScriptingTraining.com. Sie können ihn über seine Website ScriptingAnswers.com erreichen.

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