Contents
- 1 Download und Installation der PowerShell
- 2 Erste Schritte
- 3 Input Pipelining
- 4 formatieren
- 4.1 format-wide
- 4.2 PowerShell INtegrated Scripting Environment
- 4.3 Variablen
- 4.4 Parameter übergeben
- 4.5 KOmmentare
- 4.6 Sortieren
- 4.7 Escape Zeichen
- 4.8 Verzweigungen
- 4.9 Schleifen
- 4.10 PSDrives: Registry und Zertifikate wie ein Dateisystem behandeln
- 4.11 CommonParameters
- 4.12 Die wichtigsten Befehle
- 4.13 PoweRshell-Skripte anderer USer
- 4.14 PowerShell-Snapins und Module
- 4.15 Powershell-Profile
- 4.16 Ergebnisse von SQL-Statements in eine Datei exportieren
- 4.17 Powerhsell-Befehle im Hintergrund ausführen
- 5 Remoting
- 6 Eigene Funktionen
- 7 Try Cath, ErrorVairable und Trap
- 8 WMI
- 9 Schleifen
- 10 Passwörter über einen Secure Store bekommen
Download und Installation der PowerShell
die Powershell wird seit Windows Vista standardmäßig auf allen Client-Rechnern und seit Windows Server 2008 auf allen Server-Betriebssystemen ausgeliefert. Auf allen Systemen, in denen die PowerShell nicht oder nicht mehr installiert ist, kann sie nachinstalliert werden. Die PowerShell steht hier zum Download bereit.cd
Erste Schritte
Startet die Windows PowerShell. Standardmäßig wird euch dann eine Kommandozeile mit blauem Hintergrund und weißer Schrift ausgeliefert. Bevor ihr startet, solltet ihr das LAyout eurer PowerShell bearbeiten. Schiebt die Powershell an den absolut linken Rand eures Monitors. Rechtsklickt dazua uf den Fenstertitel der Windows PoweRShell und wählt Eigenschaften. Dort klickt ihr auf den Reiter Layout. Ändert unter Fensterpuffergörße die Breite des powershell-Fensters so ab, dass die PowerShell bestenfalls die gesamte Breite des Bildschirms einnimmt. Stellt danach unter FEnstergröße die Breite auf den selben WErt ein. So stellt ihr sicher, dass für Ausgaben, die sehr viel Platz brauchen, auch genügend Platz vorhanden ist.
Mit dem Kommando
get-help <Thema>
könnt ihr euch Hilfe über ein bestimmtes Thema anzeigen lassen. Wenn ihr Hilfe über get-help selbst haben wollt, gebt ihr beispielsweise ein:
get-help get-help
wenn ihr hingegen Hilfe bezüglich Powershell-Kommandos haben wollt, die mit Windows-Diensten zu tun haben, gebt ihr ein
get-help services
Mit dem Parameter -online werdet ihr euch die Microsoft Knowledge Base weitergeleitet, wo ihr euch Online-Artikel zum Thema ansehen könnt.
get-help services -online
Grundsätzlich ist die PowerShell abwärtskompatibel zur alten DOS-Eingabeaufforderung, und zwar in dem Sinne, dass alle Kommandos, die unter der Windows-Eingabeaufforderung funktionieren, auhc in der PowerShell laufen. Ich gehe in diesem Tutorial davon aus, dass ihr schon einmal grundlegend mit der Windows-Eingabeaufforderung gearbeitet habt und dass euch dementsprechend Befehle wie dir, cd, echo, cls usw. schon etwas sagen.
Und das gute ist, dass Sie mit diesem kommando auch sehr einfach ein passendes Kommando für Ihren Bedarf finden können. Nehmen wir beispielsweise einmal an, Sie wollen irgendetwas mit Ihren Windows Logs machen. DAnn würden Sie einfach nach passenden Kommandos suchen über
get-help *log*
und schon bekommen Sie eine Liste mit allen PowerShell-Themen, die auf irgendeine Art und Weise mit Logs zu tun haben – inklusive Beschreibung.
Wenn Sie hingegen eine Liste mit allen Befehlen haben wollen, kölnnen Sie das Komamndo get-command, kurz gcm, nutzen
gcm -noun *log* -CommandType cmdlet
Ohne den PArameter -CommandType würdne Sie auch .ddl-Dateien etc. bekommen, was wir hier natürlich nicht wollen.
Nun fangen wir aber in den Grundlagen bereits an, die ersten cmdlets der PowerShell zu nutzen. Nehmen wir beispielsweise an, ihr wollt euch die Eigenschaften einer Datei in der Powershell anzeigen lassen. In dem FAll tippen wir einfach ein.
get-itemproperty <datei>
Wichtig zu verstehen ist hier, dass die Powershell nicht einfach so seine Ausgabe in die kommandozeile schreibt, sondenr ein Objekt erzeugt, dessen Ausgabe man manipulieren kann. DAs heißt die Powershell gibt standardmäßig die hier angezeiten Informationen über ein Objekt aus, welches mit get-itemproperty abgefragt wurde. Ihr könnt das Objekt aber an einen anderen Befehl weiterleiten und somit die Ausgabe manipulieren. Wie unter Linux geschieht dieses Weiterleiten über eine Pipe. Wir leiten unser Objekt mal an den Befehl format-list weiter.
get-itemproperty <datei> | format-list
Ihr merkt, dass nun andere informationen dargestellt. Um vollends zu verstehen, wie das mit den ganzen Objekten nun funktioniert, könnt ihr einfach mal den Befehl dir in einem Ordner eingeben. Für jede Datei, die das kommando dir ausgibt, wird ein extra Objekt erzeugt, welche ihr gebündelt an andere Kommandos weiterleiten und prozessieren lassen könnt. Beispielsweise
dir | get-itemproperty | format-list
Ziemlich cool, oder? Vielleicht habt ihr jetzt schon eine Idee davon bekommen, warum die Powershell so mächtig ist, nämlich, weil man jetzt sozusagen objektorientiert Skripten kann.
Kennt ihr noch das Konzept aus alten Tagen, wo ihr die Ausgabe der Windows-Eingabeaufforderung nach einem Befehl über > in eine Datei umgeleitet habt? Natürlich würde diese Variante auhc noch über die Powershell gehen, denn diese ist ja abwärtskompatibel. Jedoch macht es durchaus Sinn, auch hier wieder objektorientiert zu arbeiten. Deswegen hat die Powershell hierfür einen extra Befehl, out-file. Der folgende Bvefehl gibt die Ausgabe des oberen Befehls in eine Datei test.txt aus.
dir | get-itemproperty | format-list | out-file test.txt
Beispielsweise gibt es verschiedene out-Kommands, auf die man die Ausgabe eines ovrangehenden Befehls pipen kann, beispielsweise dir | out-gridview zeigt die Ergebnisse in einem extra Windows-Fenster im Tabellen-Layout an.
get-service | export-csv c:\services.csv
erstellt eine .csv-Datei. HIngegen exportiert
get-service | export clixml c:\services.xml
eine saubere .xml-Datei. Und mit
get-service | convertto-html
konvertiert die Asugabe in eine HTML-TAbelle. Wenn Sie diese Ausgbae in eine .html-Datei speichern wollen, müssen Sie den Befehl noch auf out-file pipen
get-service | convertto-html | out-file services.html
wenn ihr die Ausgabe eines befehls an einen anderen Befehl piped, muss der nächste befehl irgendwie wissen, welchen Parameter ihr mit dieser Pipe befüllen wollt. Standardmäßig versucht die Powershell über die sogenannte By-Value methode herauszufinden, welcher PArameter des nächsten Kommandos mit der Ausgabe des Vorgängers arbeiten soll. Wenn ihr beispielsweise folgendes kommando absetzt.
get-service | stop-service
dann wird dies nicht funktionieren. Warum ist das so? nun, wenn ihr euch den Befehl get-service anseht über
get-service | gm
Dann seht ihr in der ersten Zeile den sogenannten TypeName. Das ist der Typ des ausgabeobjekts, den der befehl get-service erzeugt. Also den Typ ServiceController.
Jetzt schauen wir uns den befehl stop-serivce an über
help stop-service -full

Dabei stellt ihr fest, dass stop-service standardmäßig den Parameter -Name (1) erwartet und somit von einem einfachen String ausgeht. der Befehl get-service erzeug tallerdings einen serviceController, der mit dem PAremater -InputObject angesprochen werden muss (2). Dieser wird allerdings stnadarmdäßig nicht genommen, sondern stop-service erwartet das piping eines strings für den Parameter -Name.
eine andere Mtehode ist die Ausgabe des ersten Kommandos nicht by-Value, sondern by-PropertyName pipen. Dazu müsst ihr erst in der vollen Hilfe des zweiten komandos nach Paramtern suchen, die Pipeline-Input byPropertyName unterstützen. Und das unterstützt unser Parameter -Name zufälligerweise

Wenn wir uns jetzt nochmal get-service | gm anschauen, sehen wir, dass get-service eine AliasProperty namens Name hat. Und diese AliasProperty Name wiederum können wir nun an den Parameter -Name des Nachfolgekommandos, nämlich stop-service, pipen. Das ganze geht dann so.
get-service | select -ExpandProperty Name | stop-service
Wir wählen also aus der Ausgabe von get-service nur die Eigenschaft Name aus und pipen diese Eigenschaft Name an das cmdlet stop-service, dessen Parameter -Name wiederum den input byPropertyName akzeptiert und daher den relevanten Service stoppt. Für das cmdlet select gäbe es auch den Paramater -Property, aber manchmal kommt mit -Property eine Eigenscahft immer noch als Objekt raus und nicht als String, wie wir es in diesem Fall gebraucht hätten.
Manchmal kommt es vor, dass ein Kommando mehr Spalten ausigbt als auf den Bidlschirm passen. Also gibt es Dateine in der Powerhsell, die bestimmen, welche Spalten eines Befehls standarmdäßig ausgegeben werdne sollen. Der Befehl get-service beispielweise gibt nur drei Spatlen aus. Es ist aber möglihc, noch wesentlich mehr Spalten auszugeben. Diese findet man heraus über
get-service | get-member
Der Befhel listet alle Spalten, die man explizit einblenden kann,. (vom Typ Property, AliasProperty oder scriptProperty). Andere Datensätze sind beispielsweise vom Typ Method oder Event, die nicht explizitr eingeblendet werden können.
Stattdessen kann man aber mit Events „Befehle“ auf Objekte absetzen, die man zuvor über ein anderes cmdlet gesammelt hat. Wenn wir also beispielsweise über get-service eine Liste aller Dienste gesammelt haben, können wir alle Dienste auf einmal über das event Start starten.
get-service Start
Auch sortieren können wir ganz einfach über die powershell nach diesen spalten. Wenn wir get-service pipen auf get-member, finden wir beispielsweise die Spalte „threads“ als eine der Properties. Und nach dieser Property können wir soriteren.
get-service | sort threads
mit dem Paremter -Ascending oder -Descending kann man die Reihenfolge der Sortierung beeinflussen
get-service | sort threads -Descending
jetzt nehmen wir mal an, wir wollen nur die dienste haben, die laufen (Status RUNNING) und deren Namen die Zeichenkette „SQL“ enthält. So finden wir unter umständen alle laufenden Datenbank-Prozesse
get-service | where-object -FilterScript { $_.Status -eq 'Running' -and $_.Name -like '*SQL*'}
Hierbei durchsuchen wir also die Properties Status und Name der Ausgabe von get-service.
hierbie könnt ihr verschiedene Vergleichsoperatoren wählen wie beispielsweise
- eq – gleich
- ceq – case sensitive gleich
- like – ist wie zeichenkette
- lt – kleiner als
- gt – größer als
Input Pipelining
über select
Jetzt mal ein etwas fortgeschritteneres Beispiel. Nehmen wir mal an, ihr lasst euch mit dem Kommando
get-adcomputer -filter *
Infomrationen über die gepflegten „computer“ im Active Directory anzeigen, an denen sich Benutzer anmelden können. Dazu filtert ihr mit * nach allen Computern im Active Directory.
Ihr bekommt einen output und in der Spalte „Name“ findet ihr die Computernamen der einzelnen computer, die im Active Directory für diese Computer hinterlegt sind.
Was ist jetzt, wenn ihr für all diese ComputerNamen bestimmt informationen abfragen wollt, beispielsweise, ihr wollte euch die PRozesse aller Computer anzeigen lassen, die im Active Directory registriert sind und die gerade laufen. Somit könn tihr beispielsweise feststellen, auf welchem Server ein bestimmter Dienst läuft, wenn ihr euch nicht mehr dran erinnern könnt.
dazu müsstet ihr normalerweise das kommando
get-process -ComputerName <ComputerName>
eingeben, um alle Prozesse dieses speziellen Computers zu bekommen. Dabei müsstet ihr jetzt für jeden einzelnen Computer den computerNamen raussuchen und diesen jeweils hier eintippen.
Das ganze geht aber natürlich einfacher. mit folgendem Kommando lesen wir die spalte name aus der ausgabe des kommandos get-adcomputer aus und speichern diese als Parameter ‚computername‘. Diesen Parmeter ‚computername‘ pipen wir dann an das kommando get-process. Denn get-process besitzt einen Parameter -ComputerName, der die Prozesse des genannten Computers auflistet. Da in unserer Abfrage aber die Computernamen aller computer im Active Directory als Objekt referenziert sind, bekommen wir gleich die Prozesse aller computer eine nach dem anderen ausgegeben.
get-adcomputer -filter * | select @{n='computername';e={$_.name}} | get-process
über .csv-Datei
ihr könnt auch die Parameter eines kommandos über eine .csv-datei füttern. Beispielsweise könntet ihr vor haben, in euem Active directory eine Reihe neuer User anzulegen, die zum Monatsanfang in eurem Unternehmen beginnen. Dazu könnt ihr in der PowerShell für jeden neuen mitarbeiter eine Kommandozeile mit dem Befehl new-aduser anlegen. Die entsprehcenden Parameter des Befehls new-aduser könnt ihr euch wieder über die hilfe ausgeben lassen.
statt jedoch für jeden neuen mitarbeiter eine extra Zeile anzufertigen, könnt ihr auch die Daten der Mitarbeiter in eine .csv-datei speichern. Die .csv-Datei hätte hierbei folgendes format
samaccountname,name,department,title,city <AD-Accountname Mitarbeiter 1>,<Echter Mitarbeitername Mitarbeiter 1>,<Abteilung Mitarbeiter 1>,<Position Mitarbeiter 1>,<standort Mitarbeiter 1> <AD-Accountname Mitarbeiter 2>,<Echter Mitarbeitername Mitarbeiter 2>,<Abteilung Mitarbeiter 2>,<Position Mitarbeiter 2>,<standort Mitarbeiter 2>
Wichtig ist, dass die Namen der Attribute in der ersten Zeile samaccount, name, department etc. genau so heißenwie die Parameter des Kommandos new-aduser, was hier der fall ist.
Die übergeben wir dann an den PArameter new-aduser
import-csv neue-mitarbeiter.csv | select samaccountname,name,department,title,city | new-aduser
Ist dem nicht der fall, weil ihr beispielswiese von der Personalabteilung eures unternehmens eine falsch formatierte .csv-Datei bekommen habt, wo die erste Spalte beispielsweise so formatiert ist.
Kontoname,name,department,title,city <AD-Accountname Mitarbeiter 1>,<Echter Mitarbeitername Mitarbeiter 1>,<Abteilung Mitarbeiter 1>,<Position Mitarbeiter 1>,<standort Mitarbeiter 1> <AD-Accountname Mitarbeiter 2>,<Echter Mitarbeitername Mitarbeiter 2>,<Abteilung Mitarbeiter 2>,<Position Mitarbeiter 2>,<standort Mitarbeiter 2>
dann könnt ihr diese falsch formatierte Zeile so umbiegen
import-csv neue-mitarbeiter.csv | select @{n='samaccountname',e={$_.'Kontoname'}},<restliche Parameter>
Seine richtige MAcht entfaltet die Powershell, wie die Linux-Shell auch, wenn man Skripte damit schreibt. Powershell-Skripte werden mit der Dateinendung .ps1 gespeichert und ermöglichen es, dass dieses Skirpt dann von der PowerShell von oben nach unten prozessiert wird.
Die Powershell unterstützt das sogenannte Code-Signing, das heißt mit der Powershell ist es möglich, skripte mit Zertifikaten zu versehen. Dies soll verhindern, dass Skripte von fremdne ausgeführt werden, die unlautere Absichten hegen. Ihr werdet daher feststellen, dass ihr in einer Windows-Standardinstallation zunächst einmal keine .ps1-Skripte ausführen könnt, wenn die Sicherheitseinstellungen entsprechend gesetzt sind. Mit folgendem Befehl könnt ihr als Administrator die Sicherhehitseinstellungen so lockern, dass ihr eure eigenen Skripte ausführen könnt, aber nicht die von Fremden.
set-executionpolicy remotesigned
diese lokale Eisntellung kann durch eine Gruppenrichtlinie überschrieben werden.
Domain -> Default Domain Policy -> Edit -> Computer Configuration -> Policies -> Amdinsitrative Templates -> Windows Components -> Windows Powershell -> Turn on Script Execution.
Ein weiteres Feature von PowerShell ist, dass man Powershell-Skripte mit einem Zertifikat signieren kann. Davon profitieren vor allem Unternehmen, die bereits eine interne Public Key infrastrcuture (PKI )aufgebaut haben und daher Zertifikate ausstellen könne,n mdenen firmenintern vertraut wird.
Zur Not kann man auch sogenannte self-sgine certificates erstellen, so dass man Skripte zumindest mit einem selbsterstellten Zertifikat signieren kann.
formatieren
format-wide
PowerShell INtegrated Scripting Environment
Grundsätzlich könnt ihr Powershell-Skripte mit einem ganz normalen TExteditor schrieben. Es empfiehlt sich jedoch, hierfür stattdessen die Windows Powershell ISE zu verwenden.

Variablen
einzelne Werte, aber auch die OBjekte, die ein kommando zurückliefert, können wir in einer Variablen speichern.
Einfache WErte können ganz einfach in Variablen hinterlegt werden
$Text = "Dies ist ein Text"
Der Befehl hinterlegt Dies ist ein Text in der variable $Text. Ausgeben könnt ihr euch den WErt dieser Variablen über die PowerShell dann mittels
Write-Host "$Text"
Viel mehr Sinn macht es allerdings, Objekte in Variablen zu speichern. Beispielsweise könnt ihr so ganz einfach alle Objekte in eine Variable speichern, die das Kommando dir zurückliefert:
$alleDateienInVerzeichnis = dir
Ihr seht also, ihr schreibt hinter dem Variablennamen einfach den Befehl, den ihr ausführen wollt. Die Powershell führt ihn aus und speichert dann alle Objekte in der Variablen $alleDateienInVerzeichnis.
Diese Objekte können wir dann beipsielsweise wieder für get-itemproperty nutzen.
get-itemproperty $alleDateienInVerzeichnis
Ihr könnt in eurem Skript aber auch den User darum bitten, einen Wert einzugeben, der dann in einer Variable gespeichert wird
$name = Read-Host "Wie heißen Sie?"
Das cmdlet Read-Host stellt also dem User die Frage Wie heißen Sie?, woraufhin der User einen Namen eingeben kann, der dann in der Variable gespeichert wird.
Wir können eine Variable auch über ein Eingabefeld einlesen lassen. Sie können beispielsweise einfach mal folgenden Code ausprobieren.
OS>[system.reflection.assembly]::loadwithpartialname('Microsoft.VisualBasic') | Out-Null
OS>$computername = [Microosft.Visualbasic.interaction]::inputbox('Geben Sie einen Namen ein','Frage Titel','Standard-Vorschlag')
Alle Variablen sind im PSDrive varaible: aufgelsitet.
Eine VAriable lässt sich mit dem cmdlet REmove-Variable -name ersetzen. Hierbei darf man jedoch nicht die Variable mit dem Dolalrzeichen ansprehcen, sondern man gibt nur den Namen der Varibale an. Um also die VAriable $a zu löschen, gibt man ein
Remove-Variable -name a
natürlich kann man die ausgbae von Befehlen inv Ariablen speichern. das folgende Kommando liest in die Variable services alle gepflegten Windows-Dienste auf dme Systme ein.
$services = get-service
Es können VAriablen mit lEerzeicehn im Namen gesetzt werde, wobei man jedoch folgende syntax verwendne muss
${Alle Services} = get-service
Beim Blegen von Variablen mit String-WErten ist darauf zu achten, dass bei einfachen Anführungszeichen ein $<Name> nicht als VAriable behandelt wird, bei doppelten Anführungszeichen hingegen schon
$x = 'Welt' $y = 'Hallo $x' $z = "Hallo $x" OS>$y Hallo $x OS>$z Hallo Welt
Hallo $x
Aus der Programmierung kennt man vielleicht den VAriablentyp von Arrays, der es erlaubt, mehrere Werte in einer einzigen VAriable zu hinterlegen. Jedes cmdlet, welches mehrere OBjekte erzeugt, legt seine Objekte in einem ARray ab, wenn man die Ausgabe des cmdlets in eine Variable speichert. Beispielsweise gibt
$services = get-service
ein Array zurück. Auf die ersten zwei SErvices in der liste greift man dann etwa zu über
$services[0] $services[1]
Parameter übergeben
Wie schon beim Linux Shell Skripting könt ihr auch PArameter an ein Skript übergeben. Beispielsweise könntet ihr an den Anfang eines Skriptes schrieben
param ( $hostname = 'localhost' )
Wenn jetzt jemand das Powershell-Skript ausführt, ohne etwas dahinter einzgueben, wird der Stnadardwert localhost verwendet. Ansonsten kann jemand mit
<Pfad zur skriptdatei> -hostname meinhostname
jetzt wird das skript mit dem Wert meinhostname für den Parameter hostname ausgeführt.
KOmmentare
Wie auch bei Batch-Skripten könnt ihr mit PowerShell ganz einfach Kommentare schrieben. Neben den Kommentaren, die mit — eingeleitet werden, die wir schon aus Batch kennen
--dies ist ein Kommentar
können wir auch mehrzielige Kommenatre schreiben.
<# dies ist ein mehrzeiliger Kommentar #>
Sortieren
Die Asugbae eines Befehls lässt sich sortieren.
Escape Zeichen
Aus verschiedenen Progrmamiersprahcen kennt ihr vielleicht Escape-Zeichen wie \n, \t usw., die es ermöglichen, in die Ausgabe eines befehls einen TAbstopp oder ienen Zeilenumbruch o. Ä. einzufügen.
Auch die Powershell bietet solche Zeichen, sie werden jedoch nicht mit einem Backslash, sondern mit einem ` eingeleitet. Mehr ifnormationen findet ihr über help about_escape_characters
Verzweigungen
if
Eine If-Verzweigung ermöglicht es, eine Aktion auszuführen, wenn eine bestimmte Bedingung eintritt, und auch untershciedliche Aktionen auszuführen, wenn unterschiedliche Bedingungen zutreffen. Die if-Verzweigung prüft, ob die jeweiligen Bedingungen erfüllt werden und die PoweRShell verhält sich dann entsprechend.
Beispielsweise können Sie prüfen, ob eine Datei existiert, bevor Sie überhaupt versuchen, diese zu löschen
$dateiname = test.txt
if (test-path $dateiname) {
del $dateiname
}
Die if-Verweigung prüft, ob es im aktuellen Ordner eine Datei test.txt gibt, und falls ja, wird diese gelöscht. Trifft die Bedingung nicht zu, springt das Skript an das Ende der geschlossenen geschweiften Klammer } und würde danach weiter machen, ohne den Inhalt der if-Verzweigung auszuführen.
switch
switch eignet sich dafür, wenn man für eine einzige Variable viele verschiedene Fälle unterscheiden möchte
switch ($variable) {
'wert1' {
Befehle für Wert 1
break
}
'wert2' {
Befehle für Wert 2
break
}
default {
Standardbefehle
}
}
Schleifen
foreach
Jetzt da wir aus dem oberen Kapitel wissen, wie man mehrere Objekte in einer Variablen speichert, kommt die foreach-Schleife ziemlich handy. Nehmen wir beispielswiese mla an, ihr wollt von jeder Datei ine ienm Verzeichnis die Eigenschaften aus dem Befehl get-itemproperty in einer extra Datei haben.
$alleDateienInVerzeichnis = dir
foreach ($datei in $alleDateienInVerzeichnis) {
$infofile = $datei.name + ".info"
get-itemproperty $datei | format-list | out-file $infofile
}
Diese foreach-Schleife geht jedes Objekt, welches in der Varible $alleDateienInVerzeichnis liegt, einzeln durch und speichert das aktuelle OBjekt in der Variable $datei. Von diesem OBjekt wird die Egienschaft .name, also der Dateinamen, genommen und mit der Dateiendung .info in die Variable $infofile gespeichert.
Danach wird vom aktuellen Objekt noch die Eigenschaftenliste über get-itemproperty | format list geholt und dies dann in eine Datei gespecihert, die den Dateinamen aus der Variable $infofile bekommt.
for
Auch diese Art der Schleife kennen wir bereits aus dem Linux Shell Skritp Tutorial. Die folgende Schliefe zählt von 0-9 hoch und gibt in jedem Schleifendurchlauf die aktuelel Zahl wieder.
for ($i=0; $i -lt 10; $i++) {
write-host $i
}
PSDrives: Registry und Zertifikate wie ein Dateisystem behandeln
Die Windows PowerShell führt das Knzept der Power Shell Drives (PSDrives) ein, mit denen es beispielsweise die Möglichkeit bietet, die Windows Registry so zu navgiieren, als wäre es ein Dateisystem auf einer Festplattenpartition. Über
cd HKCKU:
kommen Sie beispielsweise in den Registry-Knoten HKEY_CURRENT_USER, über HKLM zum Zweig HKEY_LOCAL_MACHINE.
Somit können Sie die Windows Registry auf die gleiche Art und Weise manipulieren. wie lokale Systemdateien
Nicht nur die Registry, sondenr auch lokal installierte Zertifikate, beispielsweise zur SSL- oder TLS-Kommunikation, lassen sich erforschen. Dazu wechseln Sie in das PSdrive cert:.
Alle verfügbaren psdrives können Sie sich einzeigen lassen über
get-psdrive
Sie können auch seösbt ein neues PSDrive erstellen. So können Sie beispielsweise ein Dateisystem mit einem benannten PSDrive mounten statt mit einem langweiligen LAufwerksbuchstaben.
New-PSDrive -name meinOrdner -PSProvider -Root c:\Ordner
Nach diesem Befehl können wir mit dem kommando
cd meinOrdner:
in dieses Dateisystem wechseln, statt den ursprügnlichen Weg über c:\Ordner zu gehen. Bewusst muss euch natürlich sein, dass ihr dieses LAufwerk nur innerhlab von PoweRshell ansteuern könnt. Alle anderen Windows-Programme werden diesen Mechanismus nicht beherrschen.
Neben DAteisystemen kann man auch beispielsweise UNC-Pfade, Registry-Pfade usw. mounten.
CommonParameters
Wenn Sie vorher mit der cmd.exe oder mit der Linux Shell gearbeitet haben, wissen Sie, dass jedes Kommando seinen eigenen SAtz an PArametern hat. Unter Linux können Sie beispielsweise die Unterordner eines Ordners mit dem Befhel cp -R kopieren. Dabei können Sie aber nicht automatisch erwarten, dass der Befehl zum Ausschneiden/Verschieben, mv, ebenfalls einen Parameter -R hat (hat er nämlich nicht).
Unter PowerShell ist das zumindest zum TEil anders. Denn jeder, und damit wirklich jeder, Powershell-Befehl hat einen SAtz von sogenannten CommonParameters, die für jeden Powershell-Befehl gelten.
Eine Liste aller CommonParmeters bekommt ihr über
get-help about_CommonParameters
Die Hilfe listet Ihnen, was die einzlenen CommonParameters tun, daher lohnt es sich durchaus, sich diese einmal durchzulesen.
Die wichtigsten Befehle
In dieser Überschrift zeige ich Ihnen die wichtigsten Befehle, die Sie am häufigsten mit der Windows PowerShell brauchen werden.
Wenn Sie sich den Inhalt von Textdokumenten anzeigen lassen wollen, können Sie das Kommando
gc <Datei>
verwenden.
Wenn Sie zwei Versionen einer Datei miteinander vergleichen wollen – das Linux-Äquivalent wäre das kommando diff – können Sie Compare-Object verwenden.
Compare-Object -ReferenceObject (import-clixml c:\alt.xml) -DifferenceObject (C:\neu.xml)
Man kann auch beispielsweise ein altes kommando, welches mit als .xml exportiert wurde, mit der aktuellen Ausgabe eins Kommandos verlgeichen
Compare-Object -ReferenceObject (import-clixml c:\processes-alt.xml) -DifferenceObject (get-process)
Und man kann sogar nur eine bestimmte Eigenschaft eines solchen Ausgabebefehls, der seine Ausgabe in Tabellenstruktur ausgibt, vergleichen.
Compare-Object -ReferenceObject (import-clixml c:\processes-alt.xml) -DifferenceObject (get-process) -property Name
der Befehl vergleicht nur den PArameter Name.
PoweRshell-Skripte anderer USer
Unter powerhell.com/cs/media können Sie sich Funktionen und Skritpe anderer User herunterladen, um IHre Bibliothek zu erweitern.
PowerShell-Snapins und Module
die Powershell ermöglicht das LAden von Modulen. Eine Lsite aller verfügbaren MOdule kriegt man über
get-module -ListAvailable
Hierbei ist zu unterscheiden zwischen der32- und 64-Bit-Powershell. für die 64-Bit-Powershell werden mehr module verfügbar sein als für die 32-bit-Version.
Ein modul lässt sich dann in der PoweRshell laden über
import-module <Name>
dancah können wir uns die Kommandos anzeigen lassen, die mit dem Modul dazu gekommen sind
get-command -module <name>
Das ist besonders nützlich, weil es für viele Administratoinstools unter Windows extra Module für die Powershell gibt, etwa den Gruppenrichjtlinieneditor oder das Acitve Directory.
Man kann die Funktioanlitäten der Powershell mit Snapins erweitern. Eine Liste aller verfügbaren Snapins kriegt man über
Get-PSSnapin -regtistered
Will man solch ein Snapin in der aktuellen PoweRshell-Sessoin nut6zen, muss man dieses Snappin erst hinzufügen
Add-PSSnapin <name Snapin>
Nun könnt ihr euch ansehen, welche KOmmandos das Snapin zur Powershell hinzufügt
get-command -pssnapin <name Snapin>
Powershell-Profile
Unter Linux kann man verschiedene Kommandos automatisch ausführen lassen, wenn sich der Rechner neu startet oder sich beispielsweise ein User anmeldet. Dafür igbt es verschiedene Standardskripts ide unter vordefinierten Verzeichnissen liegen, beispielweise ~/.profile für eine Useranmeldung oder die Skripte unter /etc/rc<runlevel>.d für einen Neustart.
Wenn ihr wollt, dass beim STarten von Powershell verschiedene Komamndos automatishc ausgeführt werden, dann müsst ihr ein Powershell-Profil erstellen. DAs erstellt ihr unter dem Documents-Verzeichnis des Users, also beispielsweise C:\users\<meinuser>\documents\. Dort erstellen wir einen Ordner WindowsPowerShell und darin eine Datei profile.ps1
In dieses Profil könnt ihr nun Powershell-Kommandos ausführen, die bei jedem STart der Powershell automatisch ausgeführt werden sollen, eintippen und das Skript speichern. Ihr könnt nun beim nächsten Start der PowerShell eventuell eine Fehlermeldung bekommen, dass die ExecutionPolicy die Ausführng des Skripts nicht erlaubt. Diesen behebt ihr mti dem Kommando
set-executionpolicy remotesigned
im elevated Mode.
Ergebnisse von SQL-Statements in eine Datei exportieren
Viele kommandozeilen-Utilities von Datenbankmanagementsystemen unterstützten nicht die Umleitung der Befehlsausgabe in eine Datei über die gewohnten maßnhamen. Wenn Sie beispielsweise mit dem kommandozeilentool slqcmd auf einer MS SQL Server Datenbank sind und versuchen über
SELECT * FROM qs3.DDXTT~ > c:\users\qs3adm\desktop\ddxtt.txt
den inhalt der tabelle DDXTT~ in der Datenbankinstanz qs3 in eine Datei auszugeben, werden sie auf Granit beißen.
Das kommandozeilentool isql von Sybase ASE hingegen erlaubt zwar eine eingebaute Maßnahme die Ausgbae in eine Datei im format
1>select * from qs3.DDXTT~ 2>go > c:\users\qs3adm\desktop\ddxtt.txt
und mysql kennt INTO OUTFILE
MySQL>select * form DDXTT~ MySQL>INTO OUTFILE '<dateipfad>';
das war es aber auch schon. Diese Möglichkeit ist in isql und mysql von den Programmieren eingebaut worden. Sie können deshalb leider beispielsweise die Ausgabe nicht über die Powershell pipen, etwa so
1>select * from qs3.DDXTT~ 2>go | out-gridview
Um diese Schwächen der kommandozeilen-Tools diverser Datenbanken zu umgehen, gibt es verschiedene MÖglihckeiten. Zum einen liefern viele Datenbankmanagementsysteme eigene, dedizierte Tools mit, die den Inhalt von Tabellen in eine Datei exportieren. Sowohl isql als auch sqlcmd beispielsweise nutzen hierfür ein Tool namens bcp
bcp "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable" queryout "D:\MyTable.csv" -c -t , -S SERVERNAME -T
Jedoch können Sie jedoch
- nicht immer darauf verlassen, dass ein DBMS ein solcehs Tool mitliefert
- mit diesem Tool die ausgabe zwar in eine Datei exportieren, aber immer noch nicht an andere powershell-Kommandos pipen, wie etwa an out-gridview
manchmal unterstützen die command line utilities das Pipen, wenn man die Utilities auf PoweRshell-ebene aufruft und das entsprechende SQL-Statement hinten anhängt, also etwa
Powershell>SQLCMD -S <servername> -E -Q "SELECT Col1,Col2,Col3 FROM MyDatabase.dbo.MyTable"
-s "," | out-gridview
Das funktioniert jetdoch auch nicht immer.
Powerhsell-Befehle im Hintergrund ausführen
Normalerweise müsst ihr in der powoerhsell warten, bis ein kommadno fertig ist, bevor ihr einen neuen eingeben könnt. Manche befehle laufen aber etwas länger, sodass ihr normalerweise ein zweites powershell fenster aufmachen müsstet.
stattdessen könnt ihr ein powershell skript im hintergurnd als job ausführen
start-job -command { <kommando> }
solange der job läuft, könnt ihr euch seinen status einzeigen lassen über
get-job
Remoting
remoting bezeichnet die Funktion von Powershell, eine Powershell-Kommandozeile nicht nur lokal auf dem eigenen rechner, sondern auch auf einem entfernten Rechner auszuführen, auf dem die Powershell ebenfalls installiert ist.
damit das geht, muss remoting erstmal aktiviert werden. Remoting muss nur auf den Rechnern aktiviert werden, wleche Befehle vona nderen Rechnern empfangen sollen. Die Senderseite muss also nicht extra aktiivert werden. Auf der Empfängerseite geben wir ienfach ein
enable-psremoting
In Enterprise-Umgebungen gehört natürlich mehr dazu. Hierfür müssen dann nämlich Gruppenrichtlinien gesetzt werden.
Das ganze geht über
invoke-command -computer <ip adresse oder hostname entfernter computer> -ScriptBlock { <Kommandozeilen die ausgeführt werden sollen> }
Die Funktionalität kann auch 1-to-many genutzt werden. Man kann also mit einer einzigen Powershell mehrere remote-rechner fernsteuern.
invoke-command -computer rechner1,rechner2 -ScriptBlock { <komamndos> }
Diese Art des Remotings sendet ein kommando an die rechenr, die im Parmater -computer angegeben werden, und schickt ide ausgabe dieser befehle zurück an die Powershell auf dem eigenen Rechner.
die andere Art, Remoting zu nutzen, ist, sich auf einen anderen server aufzuschalten, um auf diesem Server explizit ein- und ausgabe auszuführen. Dieser modus ist dann vergleich mit einer SSh-Verbindung auf einen Linux/Unix-server. Man verbindet isch auf den Host über
new-pssesssion -ComputerName <hoistname oder ip>
Diese Art des Remoting wird ganz häufig genutzt, wenn man einen Windows Server-rechner mit der core-Option installiert hat, also der Windows Server keine grafische Oberfläche besitzt. Hierüfr muss man sich jedoch häufig mit anderen Anmeldeinfomrationen anmelden. denn der benutzer, der sich auf den entfernen Rechner aufschalten möchte, braucht dazu entsprechende rechte. Will man sich nun mit dem Windows-Benutzerkonto des Systemadministrators des Servers anmelden, gibt man diese Informationen mit dem Parameter -Credential an.
Die remote Session kann man wieder beenden über
exit-psssession
Invoke-commands auf entfernte computer können auch im Hintergrund als Job ausgeführt werdend, sodass man nicht warten muss, bis diese Kommandos ausgeführt sind, bevor man auf der powershell weiterarbeiten kann
invoke-command -computer <hostname> -ScriptBlock {<kommandos> } -asjob -jobname <name>
wir können mehrere Sessions in einer Variable speichern
$sessions = enter-pssesssion -Computername computer1,computer2
$sessions ist hierbei ein Arary. In eine einzelne Session können wir dann rein über
enter-pssesssion -session $sessions[0]
Eigene Funktionen
wie schon im shell-Skripting Tutorial werden wir auch mit der Powershell eigene Funktionen schreiben. Die Grundstruktur ist
function MeineFunktoin {
param (
$parameter1 = 'Standardwert1',
$parameter2 = 'Standardwert2'
)
Befehl1
Befehl2
}
Es ist in Powershell sogar möglich, Funktionen zu laden, damit man diese dann nicht nur in einem Skript, sondern auch im interaktiven modus, wenn man quasi die Powershell selber geöffnet hat, nutzen kann. Dazu schreibt ihr ein Skript mit der funktion und ladet die darin definierten Funktionen über
. .\<pfad zum Skript>
damit sind die im Skript befindlichen funktionen nun in eurer PowerShell-Umgebung und ihr könnt die Funktionen interaktiv nutzen.
Ein häfuiger Awnendungsfall einer Funktion ist, dass am Ende der funktion etwas ausgegeben werden soll. Dies erzielt man etwa so
function MeineFunktoin {
$variable1 = irgendeinwert
Befehle, die varaiable1 manipuulieren
Write-Output $variable1
}
MeineFunktion | ConvertTo-HTML | Out-File ergebnis.html
Diese Ausgabes Skript schriebt den Wert der $variable1 in die kommandozeile, konvertiert dieses ins .html-Format und schreibt dann eine DAtie ergebnis.html
Try Cath, ErrorVairable und Trap
Wie beim Shell Skritping gibt es auch in der Powershell einen Try-Catch-Block.
Skritpe können in verschiedene Fehler laufen. Damit unser Skript nicht einfach abbricht, wenn eine bestimmte Fehleristuation eintritt, sondern wir aktiv im Skript etwas dagegen tun können, wollen wir Fehlersituationen abfangen und behandeln.
In einem try-Block schrieben wir die Befehle rein, die wir ausführen wollen.
try {
Befehl1
Befehl2
}
In einem catch-Block schreiben wir dann rein, was passieren soll, wenn einer der im try-Block stehenden Befehle einen Fehler verursacht
try {
Befehl 1
Befehl 2
}
catch {
Gegenmaßnahme 1
Gegenmaßnahme 2
}
Manche Fehler von Befehlen können nicht standardmäßig „gecacht“ werden. DAs heißt einige Powershell-cmdlets sind standarmdäßig so konfiguriert, dass ihre Fehler nur „hinweise“ sind. ein try-catch-Block kann aber nur solche Fehler abfangen, die zum Stoppen des cmdlets führen würden (sogenannte terminating errors). Wenn euer try-catch-Block nicht funktioniert, obwohl euer Skript fehler wirft, habt ihr vermutlich so ein cmdlet vor euch liegen. Ihr könnt jedoch das Verhalten eines Befehls ändern, indem ihr dem Befehl den APrameter –erroraction STop mitgebt. jedes cmdlet hat diesen Parameter und wenn dieser auf Stop gesetzt ist, würde das Skript anhalten und der Fehler fällt somit in den try-catch-Block mit rein.
Nun fragt ihr euch vielleicht, dass diese Art der Behandlung von Fehleranalyse noch sehr grob ist, weil ihr noch nicht untershcieden könnt,w elche Art von Fehler aufgetereten ist. Ein Backup-:Skritp beispielsweise kann auf viele verschiedene Arten fehl schlagen. Etwa weil der Festplattenspeicher voll ist , keine Schreibrechte vorhanden sind oider das zu sichernde File schlciht und einfach nicht vorhanden ist.
Viele cmdlets erlauben eine Unterscheidung verschiedener Fehlerkategorien anhand der error codes, die sie schmeißen, wenn etwas schief läuft. Viele cmdlets schmeißen bei unterschiedlcihe error codes, je nachdem, was die URsache für ihr scheitern war.
Wie unter Linux könnt ihr von jedem cmdlet den Fehlercode auslesen. Dazu müsst ihr bei dem cmdlet, welches ihr ausführt, den APramteer –errorvariable mitgeben. Diesem PArameter gebt ihr den Namen einer Variable mit, in welcher der Error Code des cmdlets hinterlegt werden soll. Da ein cmdlet mehrere Fehler auf einmal produzieren kann, ist diese error Variable immer ein Array, welches mehrere Fehlermeldungen aufnehmen kann. Das heißt, wenn wir folgenden Block schreiben
try {
Befehl1 --errorvariable fehlercode
}
catch {
Write-Host $fehlercode[0]
}
dann ist $fehlercode[0] der erste Fehlercode im array $fehlercode, welches durchaus noch weitere Fehlercodes enthalten kann.
Das bedeutet nun, dass ihr in eurem catch-Block das array nach seiner Länge analysieren könnt, um festzustellen, wie viele Fehlermeldungen im Array drin sind, und dann könnt ihr schauen, welche fehler codes genau aufgetreten sind. Mit einer if-Verzweigung beispielsweise könnt ihr dann verschiedene Gegenmaßnahmen einleiten, je nachdem, welche Fehlercodes aufgetreten sind.
Ein Problem haben wir noch: Bisher können wir nur die FEhler auslesen, die einzelne cmdlets ausgeben. Denn nur cmdlets haben den PArameter –errroraction Stop und nur solche werfen daher fehler, die in einem catch-Block abgefangen werden können.
Was wir dezriet noch nicht abfangen können, sind Fehler von Methoden eines cmdlets oder von Methoden innerhlab einer selbst geschriebenen Funktion.
Diese Art von Fehler müssen wir mit einem try-Block abfangen. Der try-Block muss deifniert werden, bevor der Befehl ausgeführt wird, der möglciherweise denFehler wirft. ein trap-Block
Ein guter Artikel zum Error Hnadling in der Powershell ist hier zu finden.
WMI
WMI ist eine super Möglichkeit, um sich HArdwareinformationen vom eignene oder von entfernten Rechnern zu holen. Beispielsweise gibt folgender befehl informationen büer das BIOS bzw. UEFI des Systems aus
Gwmi Win32_BIOS
von einem entfernten Rechner über
Gwmi Win32_BIOS -computer <name oder IP>
WMI hat eine eigene Filtering-Sprache. So kann man beispielsweise mit folgendem Befehl nach Datenträgertypen sortieren
gwmi win32_logicaldisk -Filter "drivetype=3"
hierbie können als Vergleihcsoperatoren wieder die gewöhnlichen Powershell-operatoren wie beispielswiese ceq, eq, lt, gt und like benutzt werden.
Das schwieirge an der ganzen sache ist, erstmal das richtige WMI-Objekt zu finden, welches man für die gewünschte Aufgabe verwenden kann. Dabei können Drittanbietertools sinnvoll sein, wie etwa der Primaltools WMI Explorer
Auch WMI-Objekte können als Job ausgeführt werden. Dazu bedient man sich invoke-command
invoke-command -scriptblock { get-wmiobject -class win32_process } -computer <hostname> -asjob
Auf Datenbanken mit der Powershell zurgeifen
Mit Hilfe der PowerShell ist es möglich, sich auf Datenbanken zu verbinden und auf diese Abfragen abzusetzen. Solche Powershell Skripte werdne aus verschiedenen Anlässen genutzt. Beispielsweise speichern sich Datenbankadministratoren in Powershell-Skripten häufig verwendete SQL-Abfragen, die sie dann nur noch per Doppelklick und anschließender PAssworteingabe asuführen, anstatt die Kommandos jedes mal selbst ausführen zu müssen.
Desweiteren ist es möglich, automatische Backups der Datenabnk über so ein Powershell-Skjript laufen zu lassen, oder etwas jedes mal, wenn sich ein Benutzer am System anmeldet oder eine wichtige Änderung macht, einen Log-Eintrag in eine Datenbank zu schreiben. Das Powershell-Skript könnte man dann über eine Windows Active Directory Gruppenrichtlinie immer laufen lassen, sobald sich ein Nutzer an der domäne anmeldet.
Um mit Datenbanken zu arbeiten, brauchen wir erstmal einige Voraussetzungen:
- .NET Framework >= 3.5 ist auf dem Sytem installiert
- PoweRshell 2.0 und Powershell ISE sind installiert
- desweiteren ist es empfehlenswert, dass ihr nicht die 64-Bit-Version der Powershell für das Skript verwendet, sondern die 32-Bit-Version. Einige Datnebanken haben PRobleme mit der 64-Bit-PowerShell
Danach intiialisierten wir ein benötigtes Objekt über
[assembly.reflection]::loadwithpartialname('System.Data')
Dann brauchen wir einen Connection String
Schleifen
foreach
Passwörter über einen Secure Store bekommen
Wenn dir dieser Post gefallen hat, teile ihn doch auf Social Media, abonniere und verfolge mich per E-Mail, RSS-Feed, Social Media oder registriere dich auf meiner Seite. Wenn du registriert bist, like den Post bitte, wenn er dir gefallen hat!