Zuletzt aktualisiert am 25. Dezember 2023 von Lars
Jetzt lerne ich PowerShell! Maus-Schubsen ist Out, PowerShell ist angesagt. Gerade am Anfang sitzt man aber doch gerne wie der sprichwörtliche "Ochs vor dem Berg". Hier hilft dieses Tutorial weiter.
Einleitung
Grundsätzlich sollte man nicht mit der normalen PowerShell anfangen, sondern "Windows-PowerShell ISE" verwenden. Grund? Damit hat man eine Command-Line-Completion sowie eine ausführlichere Hilfe.
Man ruft "Windows-PowerShell ISE" zum Beispiel auf, indem man auf Start klickt und anfängt "Power" zu tippen.
Je nach verwendeter Version kann die Oberfläche unterschiedlich aussehen.
Teilweise müssen für bestimmte Aufgaben (z.B. Microsoft Exchange) Module nachgeladen werden.
Befehle sind in PowerHell in der Form
Verb-Substantiv [optionale Parameterliste]
aufgebaut.
Das Verb sagt, was der Befehl machen soll und das Substantiv mit was der Befehl das machen soll. Die Parameter bestimmen den Befehl genauer.
Hier Beispiele von Befehlen:
- Add-Member...
- Get-Name...
- Set-Name...
- Remove-Name...
Es gibt aber auch andere Verben als "Add", "Get", "Set" und "Remove". Durch die Kenntnis der gängigen Verben lassen sich zumindest ansatzweise schon einige Befehle erraten. Häufig wird eine bestimmte Gross-Kleinschreibung angegeben, diese kann jedoch vernachlässigt werden. Vergisst man notwenige Parameter, fragt PowerShell interaktiv nach.
Hilfe zu den Befehlen lässt sich durch die Eingabe der folgenden Befehlsfolge aufrufen:
get-help BEFEHL
Einfache PowerShell-Befehle
DIR
dir
"DIR" kommt eigentlich aus den MS-DOS-Zeiten und gibt den aktuellen Verzeichnisinhalt aus. Eigentlich aber kein richtiger PowerShell-Befehl. Funktioniert aber.
Den aktuellen Verzeichnisinhalt erkennst du am Cursor - im Screenshot oben ist das aktuelle Verzeichnis "C:\Users\Lars".
CD
cd <parameter>
Auch "CD" ist irgendwie kein richtiger PowerShell Befehl und kommt aus den MS-Dos-Zeiten. Damit wechselst du das Verzeichnis.
Du musst den Zielordner nicht komplett eingeben, du kannst auch die Anfangsbuchstaben tippen und dann die Tabulator-Taste verwenden. Die Anfangsbuchstaben müssen allerdings eindeutig sein. Falls nicht, schlägt dir PowerShell den ersten Fund vor. Wenn du nochmal die Tabulator-Taste drückst den nächsten, und so weiter. Du wirst ausserdem feststellen, dass aus dem Fall im obigen Screenshot ...
cd .\Links
... wird. Das liegt daran, dass "." immer das aktuelle Verzeichnis bezeichnet.
".." bezeichnet das Verzeichnis über dem aktuellen. Und somit kommst du so in das Verzeichnis über dem aktuellen ...
cd ..
Mit ...
cd \
... kommst du in das oberste Verzeichnis.
Get-ChildItem
Dir ist kurz, daher benutze ich diesen Befehl noch gerne. Doch PowerShell hat einen entsprechenden Befehl. Mit ...
Get-ChildItem .
... gibst du ebenfalls den Inhalt des aktuellen Verzeichnisses aus.
Ausgabeformat in PowerShell festlegen - Tabelle oder Liste
An Beispiel des Befehle "GET-VM" werden hier verschiedene mögliche Parameter gezeigt. Die Auswahl von Werten und das Ausgabeformat funktioniert aber auch bei anderen PowerShell-Befehlen.
get-vm
ergibt ...
Ausgabeformat Liste mit "fl" festlegen
Mittels "fl" (steht für "format list") lässt sich ein Ergebnis in Listenformat darstellen.
Get-ChildItem . | fl
Ausgabeformat Tabelle mit "ft" festlegen
Mittels "ft" (steht für "format table") lässt sich ein Ergebnis in Tabellenform darstellen. Häufig ist das die Standardform. Man könnte daher beim nächsten Befehl das "ft" auch weglassen und würde die gleiche Ausgabe erhalten.
Get-ChildItem . | ft
Ausgabewerte einschränken
Nehmen wir an, es soll bei der Ausgabe nur der Name angezeigt werden.
Get-ChildItem . | ft name
Die Ausgabe sieht noch etwas arg auseinandergerissen aus. Daher setzen wir hier noch den Parameter "autosize" dazu:
Jetzt wollen wir noch mehr Eigenschaften dazu ausgeben, wissen aber nicht wie diese heissen. Da hilft uns ...
Get-ChildItem . | fl *
... weiter.
Das ist nicht besonders übersichtlich, aber so kannst du herauslesen, wie du zum Beispiel Name und Erstellungszeit ausgeben kannst ...
Get-ChildItem . | ft name, CreationTime
Spiel damit ruhig mal herum. Wenn die Spalten auseinander gerissen sind, dann versuche "- autosize dahinter zu setzen". Also ...
Get-ChildItem . | ft name, CreationTime -AutoSize
Weitere PowerShell-Befehle
Remove-Item
Dieser Befehl löscht alle Dateien in einem Ordner.
Beispiel ...
Remove-Item C:\test –Recurse
... löscht alle Dateien im Ordner C:\test samt dem Ordner selbst ohne Rückfrage.
Copy-Item
Dieser Befehl kopiert Dateien.
Copy-Item <Datei1> <Datei2>
Get-Process
Get-Process zeigt alle Prozesse an, die gerade auf dem Rechner laufen, sowie zusätzliche Informationen dazu an.
Get-Process
Get-Services
Dieser Befehl zeigt alle Dienste an, die auf dem Rechner installiert sind, sowie deren aktueller Status.
Get-Services
Get-EventLog
Dieser Befehl gibt das Ereignisprotokoll aus. Beispiel ...
Get-EventLog -LogName Application
...gibt das Application-Log aus.
Ausgabe eines Befehls im nächsten weiterverarbeiten
- Weltner, Tobias (Autor)
- Butz, Thorsten (Autor)
Das haben wir oben eigentlich schon so ähnlich bei "ft" und "fl" kennen gelernt. Das Ergebnis eines Befehls wird an einen anderen weitergeleitet und von diesem weiterverarbeitet. Zwischen beiden Befehlen steht der senkrechte Strich, der auch Pipe-Zeichen genannt wird. Beispiel ...
Get-EventLog -LogName Application | Out-Host -paging
Dieses Beispiel funktioniert nicht in der ISE, sondern in der normalen PowerShell. Die lange Liste, die der Befehl "Get-EventLog" ausgibt, wird an "Out-Host" weitergeleitet und seitenweise unterbrochen.
Wenn du mit Hyper-V arbeitest, funktioniert die folgende Befehlskette so...
Get-VMsnapshot -VMname * | Remove-VMsnapshot
... dass der erste Befehl alle Snapshots ausgibt und der zweite diese löscht.
Scripting mit PowerShell
Interessant wird das Skripting, also das Aneinanderreihen von mehreren Befehlen in einer Datei. Diese können dann wiederum am Stück ausgeführt werden.
Hierzu wird, am Besten in der ISE, eine entsprechende Datei mit der Endung .ps1 angelegt. Eventuell musst du hierzu in der ISE noch der "Skript Pane" bzw. "Skriptbereich" aktiviert werden.
Schauen wir uns das folgende Skript an:
$VMname = Read-Host "Geben Sie den Namen der neuen VM ein" Write-Host "Erstelle neue VM: $VMname" New-VM -Name $VMname
Mit dem Skript oben haben wir auch Variablen unter PowerShell kennen gelernt. Diesen wird einfach ein $ vorangestellt. Sie können direkt im Text ausgegeben werden. Der erste Befehl liesst den Namen einer VM vom Benutzer interaktiv ein, der zweite gibt den Namen zur Kontrolle aus und der dritte erstellt eine neue VM (ohne zusätzliche Parameter).
Variablen kann man sich als Speicherzelle ähnlich dem Speicher eines Taschenrechners vorstellen. Variablen können Werte zugewiesen werden und man kann den Wert einer Variablen auch abfragen.
Ein Skript, das mit der Endung ps1 gespeichert wird, startet jedoch nicht durch Doppelklick, sondern es muss immer zwangsläufig innerhalb einer PowerShell gestartet werden.
Zeitgesteuertes Ausführen eines PowerShell-Skriptes
Zeitgesteuertes Ausführen eines Programmes erledigt man unter Windows mit dem Programm "Aufgabenplanung".
Da PowerShell-Skripte nie direkt, sondern immer nur innerhalb einer PowerShell ausgeführt werden können, gilt es einiges zu beachten beim zeitgesteuerten Ausführen.
Unter "program/script" trägt man den Pfad zur PowerShell ein.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe
Unter "Add arguments (optional)" den Skriptnamen inkl. Pfad mit vorangestelltem "-command", also z.B.
-command "C:\Windows\bat\myscript.ps1"
Kommentare
Zeilenweise Kommentare werden durch ein # eingeleitet. Kommentare werden eingesetzt, um bestimmte Aktionen im Skript zu dokumentieren. Oft aber auch, um einfach eine Anweisung zu deaktivieren.
Schleifen und if-Abfragen in PowerShell
Ich lerne am liebsten anhand von Beispielen. Auf mcseboard.de habe ich ein schönes PowerShell-Beispiel gefunden, was anschaulich Schleifen und if-Abfragen zeigt. Auch hier sieht man wieder eine gewisse Verwandtschaft zu PHP in der PowerShell-Syntax.
Das folgende Skript listet alle Dienste auf ("get-service") und führt darüber eine Schleife aus ("foreach"). Dann prüft es, ob der aktuelle Dienst den Status "Running" hat und färbt den Eintrag entsprechend. Die Ausgabe auf die Konsole erfolgt mit dem Parameter "write-host".
$svcs = get-service | Sort-Object Name foreach($sv in $svcs) { if($sv.Status -eq "Running") { write-host -ForegroundColor Green $sv.Status $sv.Name $sv.DisplayName } else { write-host -ForegroundColor Red $sv.Status $sv.Name $sv.DisplayName } }
Vergleichsoperationen in PowerShell
Im obigen Beispiel haben wir bereits den Vergleichsoperator
-eq
kennen gelernt. Er prüft auf Gleichheit. Welche weiteren Operatoren sind verfügbar?
-ne
ungleich
-lt
kleiner
-le
kleiner oder gleich
-gt
grösser
-ge
grösser oder gleich
-and
und
WMI-Abfragen mit PowerShell
Auch WMI-Abfragen lassen sich relativ leicht mit PowerShell realisieren. Häufig kommt man bereits mit dem folgenden kurzen Befehl an die Seriennummer eines Servers.
Get-WmiObject Win32_BIOS
WMI und PowerShell Praxis-Beispiel. Temperaturüberwachung von HP Proliant-Server
Machen wir noch ein praktisches Beispiel. HP-Server haben jede Menge Temperatursensoren verbaut. Einer dafür eignet sich dazu, die Umgebungstemperatur zu überwachen.
$colItems = get-wmiobject -class "HP_NumericSensor" -namespace "root\hpq" -computername "." foreach ($objItem in $colItems) { if ($objItem.Name -eq "Temperature Sensor 1") { $date = (get-date).ToShortDateString() $time = (get-date).ToShortTimeString() $temperature = $objItem.CurrentReading write-host "$date $time Umgebungstemperatur: $temperature Grad" } }
Nur der Sensor mit dem Namen "Temperature Sensor 1" liefert den relevanten Wert, daher wird auch nur dieser abgefragt.
Die Befehle
$date = (get-date).ToShortDateString() $time = (get-date).ToShortTimeString()
liefern uns Datum und Uhrzeit vernünftig formatiert zurück.
Text-Dateien erzeugen mit PowerShell
Das obige Beispiel "Temperaturüberwachung von HP Proliant-Server" lässt sich noch erweitern. Wir können eine INI-Datei erzeugen, die von einem Monitor-Programm ausgewertet werden kann.
$colItems = get-wmiobject -class "HP_NumericSensor" -namespace "root\hpq" -computername "." foreach ($objItem in $colItems) { if ($objItem.Name -eq "Temperature Sensor 1") { $date = (get-date).ToShortDateString() $time = (get-date).ToShortTimeString() $temperature = $objItem.CurrentReading write-host "$date $time Umgebungstemperatur: $temperature Grad" "[Standard]" | out-file -filepath C:\windows\bat\tempcheck\temperature.ini "temperature=$temperature" | out-file -append -filepath C:\windows\bat\tempcheck\temperature.ini } }
Mittels Out-File lassen sich Ergebnisse von Befehlen oder Variablen in eine Text-Datei schreiben. Ohne die Option -append, wird die Datei immer wieder neu erstellt.
Interessante PowerShell-Beispiele
Verschlüsselte GMX-Mails via PowerShell versenden:
Falls du automatisiert E-Mails via GMX versenden willst, geht das nur noch verschlüsselt. Früher war das Tool "bat" die erste Wahl, das kann jedoch kein SSL mehr. Mit PowerShell gehts auch, nur braucht es da einige Schritte.
Nehmen wir an, Ihre Absenderadresse ist:
monitoring.kaktus@gmx.de
Ihr Password wäre (geht nicht, also nicht probieren):
kakti!0815
Ihre Zieladresse ist:
ziel@kaktus.de
Mit folgendem Skript versendest du die E-Mail:
$smtpServer = "mail.gmx.net" $smtp = new-object Net.Mail.SmtpClient($smtpServer) $credentials=new-object system.net.networkcredential("monitoring.kaktus@gmx.de","kakti!0815") $smtp.credentials = $credentials.getcredential($smtpserver,"25","basic") $message = New-Object Net.Mail.MailMessage("monitoring.kaktus@gmx.de","ziel@kaktus.de") $message.Subject = "Hello from PowerShell" $message.Body = "Dieses wunderbare Mail stammt von der PowerShell..." $smtp.Send($message)
Update
Noch besser scheint es mit dem folgenden Mail-Code zu funktionieren
$EmailTo = "empfaenger@meine-email.com" $EmailFrom = "absender@gmx.ch" $Subject = "Host: $Server - Lauferk: $Device - Platz wird knapp: $Ratio Prozent" $Body = "Hallo!`r`n Host: $Server - Lauferk: $Device - Platz wird knapp. $Ratio Prozent." $SMTPServer = "mail.gmx.net" $SMTPMessage = New-Object System.Net.Mail.MailMessage($EmailFrom,$EmailTo,$Subject,$Body) $SMTPClient = New-Object Net.Mail.SmtpClient($SmtpServer, 587) $SMTPClient.EnableSsl = $true $SMTPClient.Credentials = New-Object System.Net.NetworkCredential("monitoring.kaktus@gmx.de","ziel@kaktus.de") $SMTPClient.Send($SMTPMessage)
Freien Speicherplatz auf lokalen Laufwerken mit PowerShell überprüfen
Eine voll gelaufene Partition ist eines der häufigsten Fehlerursachen. Sinnvoll wäre es, wenn der Support rechtzeitig einen Fehlerhinweis hierzu bekäme. Auch dies können wir mit PowerShell und WMI-Abfragen realisieren:
function Round( $value, [MidpointRounding]$mode = 'AwayFromZero' ) { [Math]::Round( $value, $mode ) } function sendmail ($Server, $Device, $Ratio) { $Ratio = $Ratio * 100 $Ratio = Round $Ratio write-host $Server $Device $Ratio $smtpServer = "mail.gmx.net" $smtp = new-object Net.Mail.SmtpClient($smtpServer) $credentials=new-object system.net.networkcredential("monitoring.kaktus@gmx.de","kakti!0815") $smtp.credentials = $credentials.getcredential($smtpserver,"25","basic") $message = New-Object Net.Mail.MailMessage("monitoring.kaktus@gmx.de","ziel@kaktus.de") $message.Subject = "Host: $Server - Lauferk: $Device - Platz wird knapp: $Ratio Prozent" $message.Body = "Hallo!`r`n Host: $Server - Lauferk: $Device - Platz wird knapp. $Ratio Prozent.`r`nBitte beachten." $smtp.Send($message) } Clear-Host $Computername = "MyHost" $colItems=Get-WmiObject win32_logicaldisk -ComputerName $Computername -Filter "Drivetype=3" write-host $Computername foreach ($objItem in $colItems) { write-host ---- $objItem.DeviceID ---- $Size = [decimal]$objItem.size / 1024 / 1024 / 1024 $Size = Round $Size write-host Gesamt: $Size $Free = [decimal]$objItem.Freespace / 1024 / 1024 / 1024 $Free = Round $Free write-host Frei: $Free $Ratio = $Free/$Size write-host Ratio: $Ratio if ($Ratio -le 0.1) { sendmail $Computername $objItem.DeviceID $Ratio } }
Idee / Danke an:
- stackoverflow.com/questions/36355271/how-to-send-email-with-powershell
- stackoverflow.com/questions/32796607/powershell-send-email
- philerb.com/2011/11/sending-mail-with-powershell/
Funktionen in PowerShell
Schauen wir uns zum Verständnis Funktionen in PowerShell näher an:
function Funktion( Werte ) { Anweisungen }
PowerShell macht keine Unterschiede zwischen Prozedur und Funktion. Das was wir von anderen Sprachen als Prozedur kennen, ist in PowerShell eine Funktion ohne Rückgabewert.
Rückgabewerte in PowerShell verhalten sich komplett anders als in anderen Sprachen, ich werde hier daher erst mal nur sehr kurz darauf eingehen. Wie in anderen Sprachen gibt es zwar das Schlüsselwort return, es kann aber auch leer sein. Es sagt nur, dass alles, was zuvor ausgegeben wurde, zurückgegeben wird.
Ein kleines Beispiel:
function testfunction { $a = "Hello, World" $a $a return } Clear-Host $result = testfunction Write-Host $result
Da $a zwei mal in der Funktion ausgegeben wird, was aber aufgrund der Kapselung nicht an der Konsole erscheint, wird der Rückgabewert (und die Ausgabe) "Hello, World Hello, World" sein.
WMI mit PowerShell
Zurück zur eigentlichen Funktion:
Mit...
$colItems=Get-WmiObject win32_logicaldisk -ComputerName $Computername -Filter "Drivetype=3"
...werden Laufwerke angesprochen. Durch die Filter-Option wird der Zugriff auf lokale Laufwerke beschränkt.
Mit der Schleife wird Laufwerk für Laufwerk "durchgescannt. Der Rückgabewert in Bytes wird in Gigabytes umgerechnet. Ist das Verhältnis < 0.1, wird die Funktion aufgerufen, die eine Mail verschickt. Mehr Infos zur WMI-Geschichte gibt es unter Working with WMI providers to PowerShell.
- Weltner, Tobias (Autor)
- Weltner, Tobias (Autor)
Weitere Beispiele
FAQ Windows PowerShell
Windows PowerShell ISE fehlt
Windows PowerShell ISE ist auf Windows-Servern ein Feature, das nachinstalliert werden muss. Du findest es unter "Rollen und Features hinzufügen".
PowerShell-Skripte können nicht ausgeführt werden
Erhältst du die Meldung "Die Datei ... kann nicht geladen werden, da die Ausführung von Skripts auf diesem System deaktiviert ist. Weitere Informationen finden Sie unter 'about_Execution_Policies' (http://go.microsoft.com/fwlink/?LinkID=135170)", so musst du zunächst die Ausführung von PowerShell-Skripten freischalten. Hierzu rufe die PowerShell bzw. die PowerShell-ISE mit administrativen Rechten auf. Anschliessend gibst du den folgenden Befehl ein ...
Set-ExecutionPolicy Unrestricted
Nun ist das System aber offen für nicht signierte und eventuell für bösartige Zwecke geschriebene PowerShell-Skripte.
Weitere Lernmöglichkeiten für PowerShell
- Powershell Tutorial for Beginners: Learn in 1 Day (Englisch)
- PowerShell 5: Windows-Automation für Einsteiger und Profis
- Windows PowerShell 5 - kurz & gut
Hallo, hier schreibt Lars. Dipl-Ing. Ingenieurinformatik (FH). Seit Jahrzehnten in der IT tätig. Geprüfter (und begeisterter) Webmaster. Ebenso begeisterter Windows-, Apple-, und Office-User. Ich schreibe über alle möglichen Themen rund um IT. Mehr über mich erfährst du hier: Über mich. Danke für deinen Besuch!
Moin,
ich habe bisher nur die Einleitung gelesen und kann nur sagen: Bitte nochmal auf Rechtschreibfehler/Tippfehler korrigieren. Es ist verständlich, was Sie meinen, aber nicht gut zu lesen.
Liebe Grüße
Hallo Max(?)
Danke für die berechtigte Kritik. Habe die Überarbeitung des Artikels ganz nach oben auf die To Do Liste gesetzt. Wird demnächst kommen.
Gruss
Lars
sorry, aber ein "Einführungstutorial" sollte für Anfänger verständlich sein. Das ist leider überhaupt nicht der Fall. Schon im ersten Absatz:
"Grundsätzlich sollte man nicht mit der normalen PowerShell anfangen, sondern die Windows-PowerShell ISE verwenden. "
Wofür steht ISE? Was sind die Unterschiede?
Dann geht es weiter mit
"Die Namensgebung der meisten Befehle besteht aus:
•Get-Name…
•Set-Name…
•Remove-Name…"
Häh? Was ist eine Namensgebung? Wofür brauche ich die?
Und so geht es immer weiter...leider.
Hallo Leo
Danke für die berechtigte Kritik. Habe die Überarbeitung des Artikels ganz nach oben auf die To Do Liste gesetzt.
Gruss
Lars
ISE steht für Integrated Script Environment
ne, integrated script engine
Nicht streiten, aber schaut auch mal hier: https://de.wikipedia.org/wiki/PowerShell