Windows-Systemkomponenten

Windows Powershell richtig nutzen

21.01.2014 von Hermann Apfelböck
Mit der Windows Powershell lassen sich viele Probleme ganz einfach lösen. Und sie bietet mehr Möglichkeiten als die klassische Kommandozeile CMD. Dieser Artikel liefert viele Praxistipps zur Nutzung der PowerShell.

Per Kommandozeile kann man viele Aufgaben einfach und vor allem schnell erledigen. Warum es nicht mehr unbedingt die CMD sein muss, zeigen wir Ihnen an einigen Beispielen, die für sich sprechen. Aktueller Stand der Powershell ist Version 3.0 unter Windows 8 und RT, unter Windows 7 läuft die ältere Version 2.0, man kann die neue Version aber nachinstallieren.

Powershell versus textbasierte Shells

Powershell und textbasierte Eingabeaufforderung: Eine knappe und nachvollziehbare Powershell-Pipeline erledigt das, was in der Cmd.exe eine komplexe Batchdatei erfordert.

Angenommen, Sie möchten sich die Dateien eines großen Ordners nach den Dateierweiterungen sortieren lassen, aber die Liste sollte die kompletten Pfadnamen anzeigen. Irgendwie ist diese Aufgabe mit der CMD unter Windows oder einem Unix-Terminal schon machbar: Man muss die richtigen Kommandos kennen und deren Textauswurf geschickt filtern und sortieren. Auf dem Bild sehen Sie eine Batchdatei, die diese Aufgabe leistet. Eventuell geht das auch noch effizienter - aber wirklich einfach auf keinen Fall. Sie müssen in jedem Fall einen neue Funktion in Form einer Batchdatei basteln und dann dafür sorgen, dass diese im Systempfad erreichbar ist.

Verblüffend einfach erledigen sich solche Aufgabenstellungen mit der Powershell unter Windows 7 und 8:

dir -recurse | sort extension | select fullname

Das ist nicht nur vergleichsweise simpel, sondern nebenbei auch noch deutlich schneller als die Ausgabeverarbeitung der textbasierten CMD-Shell.

Das entscheidende Alleinstellungsmerkmal der Powershell heißt: Objektorientierung im Verbund mit Pipelines, die mit dem Zeichen "|" realisiert werden. Pipelines gibt es auch bei textbasierten Kommandointerpretern, aber die Filter-Pipes wie "Sort" oder "Find" in der Cmd-Eingabeaufforderung liefern einfach nur Text; die Pipes in der Powershell transportieren hingegen das gesamte Objekt inklusive aller Eigenschaften und Methoden.

Die unglaubliche Vermehrung der Eigenschaften: Erst ein "select *", also die Auswahl aller Eigenschaften zeigt den vollen Umfang der objekte - hier der Prozess "Winword".

Der Befehl oben listet also alle Dateien auf, sortiert diese nach der Extension, und danach können Sie mit "select" jede Eigenschaft abrufen, die Sie sehen wollen. Ein erweitertes "select length,extension,fullname" zeigt dann neben den Pfadnamen auch noch Dateilängen und Erweiterungen. Ein weiteres Beispiel zeigt den Unterschied zwischen der Textausgabe klassischer Shells und der objektorientierten Powershell:

$a=get-process

Das Kommando schreibt die laufenden Prozesse in die Variable $a (Variablen, gleich welchen Typs, werden mit"$" gekennzeichnet). Nachfolgendes

$a

zeigt dann die Prozessliste mit acht wesentlichen Eigenschaften an. Diese Repräsentation ist aber nur freundliche Kurzzusammenfassung der Shell. Die Variable $a enthält in Wahrheit deutlich mehr:

$a | select *

Jetzt zeigt die Variable zu jedem Prozess nicht mehr nur acht, sondern über 60 Eigenschaften. Um herauszufinden, welche Eigenschaften und Methoden für ein Objekt insgesamt vorliegen, und welche davon Sie interessieren, gibt es einen systematischen Weg:

dir c:\| get-member

"dir" (eigentlich "get-childitem") liefert in diesem Fall Datei-Objekte. Deshalb erscheint eine umfangreiche Liste der Eigenschaften und Methoden für Dateien und Ordner, so etwa "Delete", "Attributes", "Length" oder "CreationTime". Über "get-member" ermittelte Eigenschaften helfen dann, die Ausgabe oder eine Objekt-Variable genau auf das inhaltlich Gewünschte einzugrenzen:

dir c: -recurse -include *.xls? | where {$_.creationtime -gt "01.01.2013"} | select lastaccesstime, length, fullname

Der "Dir"-Befehl filtert Excel-Dateien, der "Where"-Filter lässt davon nur die jüngst genutzten Dateien übrig, und "Select" reduziert dann die angezeigten Objekteigenschaften.

Die neue "Eingabeaufforderung" kann mehr

Alles, was Sie üblicherweise in der Cmd-Eingabeaufforderung machen, kann die Powershell mindestens auch: Sie startet praktisch alles, womit man sie füttert: Ausführbare Dateien wie .exe, .cmd, .msc, .vbs lädt die Powershell ebenso wie Benutzerdateien wie etwa .docx, .jpg, .xls, .pdf, wobei sie diese direkt zum passenden Programm schickt.

Natürlich können Sie innerhalb der Powershell auch alle Kommandozeilen-Tools verwenden etwa Robocopy, Fsutil, Taskkill oder auch die Eingabeaufforderung Cmd. Übrigens: Steht ein Dateiname in Anführungszeichen, muss "&" vorangestellt werden, um den Befehlszeilenmodus zu erzwingen.

Die Powershell startet alles: Programme, die nicht im Systempfad liegen, findet das Cmdlet "StartProcess" oder abgekürzt "start".

Bei der Bedienung gibt es starke Ähnlichkeiten mit der gewohnten Kommandozeile cmd.exe: Das Editieren der Zeilen geschieht auf dem Prompt auf vergleichbare Weise. Das gilt für die automatische Pfad- und Datei-Namenserweiterung mit der-Taste, ebenso wie für die History-Funktion, bei der Sie mit Cursortaste die letzten Befehle zurückholen. Zahlreiche Aliases für die umständlichen Cmdlets orientieren sich an alten Cmd-Kommandos ("dir", "del", "cls", "ren", "md", "type" …). Wenn Sie schnell was rechnen müssen, geben Sie am Prompt einfach den Term ein:

455*0.19+455

Die Powershell holt ferner mit dem internen Befehl "Get-WmiObject" (Abkürzung "gwmi") umweglos alle Informationen aus der WMI (Windows Management Instrumentation). So liest etwa "(gwmi Win32_OperatingSystem).LastBootUpTime" die Eigenschaft des letzten Systemstarts aus der WMI-Klasse Win32_OperatingSystem. Besser lesbar wird die Zeitangabe durch eine Konvertierung:

$b=GWMI Win32_OperatingSystem$b.ConvertToDateTime($b.LastBootUpTime)

Meldungen der Powershell: die Fehlerinformationen sind aussagekräftig und hilfreich, verwenden aber gruselige Farbcodes. Dies lässt sich aber umstellen.

Nebenbei steuert die Powershell auch COM-Anwendungen wie den Internet Explorer oder Office-Programme. Diese Möglichkeiten erfordern fast immer eine kleine Funktion oder ein Script. Als Befehlsfolge am Prompt sieht das wie folgt aus:

$ie = new-object -ComObject "internetexplorer.application"$ie.navigate("www.google.de")$ie.visible=1

Die Windows-Registry ist standardmäßig als Laufwerk in die Powershell gemountet. Wenn Sie sich alle virtuellen Laufwerke mit

get-psdrive

auflisten, finden Sie auch "HKCU" und "HKLM", also die Hauptschlüssel der Registry. Auf diese können Sie mit "cd" oder "dir" wie auf das Dateisystem zugreifen:

cd hklm:\software\classes\exefiledir

"cd" und "dir" sind Aliases für die eigentlichen Cmdlets "set-location" und "get-childitem". Das Beispiel zeigt, dass die Shell in der Registry, in Funktionen und Variablen ebenso wie in Datei-Ordnern spazierengeht. Ändern, Löschen, Eintragen ist natürlich mit den passenden Cmdlets ebenso möglich. Der folgende Befehl

get-itemproperty "hkcu:\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"

zeigt die Windows-Standardordner des aktuellen Benutzers aus dem betreffenden Registry-Schlüssel.

Powershell und pS1-Scripts

Die Überlegenheit der Powershell gegenüber der Cmd.exe ist deutlich. Trotzdem fällt vielen der Umstieg schwer, die sich jahrelang an die Eigenheiten der Eingabeaufforderung gewöhnt hat. Einige Aliases, die diesem Umstand Rechnung tragen, gibt Microsoft der Powershell bereits mit - so etwa das erwähnte "dir" für "get-childitem" oder "del" für "remove-item". Den Vorrat der Alias-Befehlsabkürzungen können Sie aber jederzeit erweitern: Eigene Aliases sind mit Befehlen wie

new-alias n notepad.exe

schnell angelegt (um mit "n" den Editor zu starten). Der Wert solcher Aliases ist aber begrenzt, da sie nur als Kommandoabkürzung taugen und keinerlei Argumente zulassen. Weit leistungsfähiger sind Funktionen:

function n {notepad.exe $args}

Jetzt kann auf dem Prompt der Dateiname gleich mitgegeben werden. $Args ist eine Standardvariable, die sämtliche oder einzelne Argumente weitergibt. Da der Powershell-Prompt eine Eingabe wie "3.14 * 6.34" oder "0x2A1" (Hex-Zahl) direkt als Rechenaufgabe interpretiert und löst, können Sie mit etwas Code auch komplexere Aufgaben umsetzen:

function Tage {((get-date("$args"))-(get-date)).days}

Die Eingabe "tage 22.10.2009" gibt dann die Anzahl der Tage bis zum eingegebenen Datum zurück.

Ganz ohne Scripts geht’s nicht: daher sollten sie das unsinnige Script-Verbot der Powershell mit "set-executionpolicy unrestricted" abstellen. Das gelingt nur mit Admin-Rechten.

PS1-Scripts anlegen: Der in einer Funktion abgelegte Code gilt nur so lange, bis die Shell geschlossen wird. Daher stellt sich auch für sporadische Benutzer der Powershell sehr schnell die Frage, wie sich komplexere Funktionen, Befehle oder Aliases dauerhaft speichern lassen. Ähnlich wie Cmd benutzt die Powershell einfache Textdateien als Script-Format, die Sie mit jedem Texteditor wie Notepad erstellen können. Entscheidend ist dabei die Endung ".ps1".

Ein Sonderfall ist das Script Profile.ps1, das die Shell beim Start automatisch einliest - der ideale Ort für persönliche Funktionen, Variablen und Aliases. Der Standardpfad der aktuellen Version 3.0 ist "%windir%\System32\WindowsPowerShell\v1.0". Eine hier abgelegte Profile.ps1 lädt die Powershell beim Start in jedem Fall. Besser und sauberer ist es aber, die Profile.ps1 im Benutzerprofil abzulegen. Der korrekte Ordner dafür ist "%userprofile%\Documents\WindowsPowerShell". Als einfachste Anpassungen könnten Sie kleine Navigationshilfen in die neu angelegte Profile.ps1 einbauen - etwa um mit "d" zum Desktop zu wechseln:

Function d {push-location"${env:userprofile}\Desktop"}

Ebenso nützlich kann eine einfache Funktion sein, die das aktuelle Verzeichnis als Explorer-Fenster startet:

Function ex {explorer.exe$(get-location).path}

Alle Cmdlets: in Version 3.0 liefert der Hilfsbefehl "ShowCommands" eine Übersicht zu allen Powershell-Kommandos.

Scripts freischalten: Nach ersten Anpassungen der Profile.ps1 erleben Sie beim Start der Powershell erst mal eine enttäuschende Bremse. Wenn Sie die Powershell vorher nie genutzt haben, ist jede Script-Ausführung erst mal verboten. Sie müssen erst dieses Verbot aufheben. Starten Sie dazu die Powershell über das Startmenü von Windows 7 oder 8 mit der Option "Als Admin[istrator] ausführen". Sie benötigen Adminrechte, um mit

Set-ExecutionPolicy unrestricted

den nötigen Eintrag in der Windows-Registry machen zu dürfen. Danach sind alle PS1-Scripts sofort erlaubt und lauffähig.

Weitere Beispiele und Tipps

Es ist entscheidend, Pipelines der Powershell in der richtigen Abfolge anzusetzen. Wenn Sie mit folgendem Befehl

dir -recurse *.xlsx | select fullname | where {$_.CreationTime -gt "12.12.2012"}

versuchen, die jüngeren Excel-Dateien aufzulisten, erhalten Sie kein Ergebnis. Sie haben nämlich mit "Select" die vielen Eigenschaften von Dateiobjekten auf eine einzige reduziert - "Fullname" (Pfad plus Name). Die nachfolgende Suche nach dem Erstelldatum (CreationTime) ist somit sinnlos, weil das Objekt diese Eigenschaft nicht mehr enthält. Eine Umstellung führt zum erwarteten Ergebnis:

dir -recurse *.xlsx | where {$_.CreationTime -gt "12.12.2012"} | select fullname

Die umfangreichen Script-Möglichkeiten, um Objektvariablen weiter zu bearbeiten, können wir hier kaum andeuten. Sie entsprechen in vielen Belangen der Syntax von Unix-Shells, sind aber auch für jeden WSH-oder Batch-Erfahrenen durchaus zugänglich - an "If", "For", "Foreach", "While" oder "Switch" in der einen oder anderen Form kommt keine Sprache vorbei. Den simpelsten Einstieg für erste PS1-Scripts bieten Filter, die den Datenstrom der Pipeline entweder weiterfließen lassen oder nicht. Die einzelne Instanz wird in jedem Filter (auch in "Where" oder "Foreach") mit der globalen Variable "$_" bezeichnet. Darf das Objekt oder eine Eigenschaft desselben "durch", schreibt man einfach "$_". Ein ganz einfaches Beispiel:

Filter Dirs {if ($_.parent) {$_}}

Dieser Filter lässt nur Ordner durch, weil Dateien die Eigenschaft "Parent" fehlt.

dir -recurse | Dirs | select fullname

Powershell isE mit Intellisense: Für script-Profis ist das isE (integrated scripting Environment) recht nützlich. Für den interaktiven Gebrauch reicht die normale Shell.

Der "Dir"-Befehl mit dem vorher definierten Dirs-Filter listet dann folglich nur noch die Ordner auf. Für einfache Text- oder HTML-Dateien bietet die Powershell eine schnelle Textsuche. Dabei können Sie sich mit "Select" die Fundstellen, die Trefferdateien und bei Bedarf weitere Eigenschaften ausgeben lassen:

dir -recurse *.txt | SelectString -SimpleMatch "Venedig" | select path,line | format-list

Eine seit Version 2.0 eingeführte attraktive Ausgabe-Variante ist "Out-Gridview". Die Objektdaten werden grafisch dargestellt und lassen sich filtern und sortieren:

get-scheduledtask | select taskname,taskpath,state, description | out-gridview

Eine weitere große Hilfe wurde mit Version 3.0 eingeführt: Mit "Show-Commands" erhalten Sie eine Übersicht über alle internen Befehle, die sich auch nach Modulen filtern lassen, etwa nach "NetAdapter" oder "BitLocker". Denselben Service bietet standardmäßig das "Windows Powershell ISE" (Integrated Scripting Environment). Dieses Tool ist aber für gelegentliches, interaktives Verwenden der Powershell nicht notwendig. (mje)

Dieser Artikel basiert auf einem Beitrag unserer Schwesterpublikation PC Welt.