- 1 Section
- 10 Lessons
- unbegrenzt
- PowerShell – Grundlagen bis Automation10
- 1.1Was ist PowerShell? Versionen und ISE vs. VS Code
- 1.2Cmdlets: Verben, Substantive, Get-Help
- 1.3Variablen, Datentypen und Pipeline
- 1.4Kontrollstrukturen: if, switch, for, foreach, while
- 1.5Funktionen und Module
- 1.6Dateisystem und Prozesse verwalten
- 1.7Active Directory mit PowerShell verwalten
- 1.8Netzwerkbefehle: Test-NetConnection, Resolve-DnsName
- 1.9Skripte planen: Task Scheduler
- 1.10Praxisprojekt: AD-Onboarding-Skript
Variablen, Datentypen und Pipeline
In L2 hast du Cmdlets kennengelernt – wie man Befehle aufruft. Jetzt schauen wir was zwischen ihnen passiert: die Pipeline. Das ist das Herzstück von PowerShell, und der Punkt wo der „Objekte statt Text"-Vorteil aus L1 wirklich zum Tragen kommt. Wer Pipeline und Variablen verinnerlicht hat, hat PowerShell verstanden.
Wir behandeln drei eng verwandte Themen: Variablen (Werte speichern), Datentypen (was für Werte sind das?) und die Pipeline (wie Objekte zwischen Cmdlets fließen). Achtung: das hier ist die Lektion mit den größten Unterschieden zu Bash. Wer aus Bash-Welt kommt, muss umdenken.
1) Variablen anlegen und nutzen
PowerShell-Variablen beginnen mit $. Anders als bei Bash dürfen rund um das = Leerzeichen stehen – ist sogar Konvention:
Ein riesiger Unterschied zu Bash: PowerShell-Variablen können nicht nur Strings enthalten, sondern beliebig komplexe Objekte. $processe oben ist kein Text – es ist eine Liste von Process-Objekten, jedes mit dutzenden Properties. Du kannst sie filtern, sortieren, zählen, einzelne Properties auslesen – alles ohne Re-Parsen.
2) Datentypen – mehr als nur Strings
PowerShell kennt im Gegensatz zu Bash echte Datentypen. Die wichtigsten:
"Hallo". Default für Werte in Quotes.$alter = 25$preis = 19.95$true oder $false.@(1,2,3) oder 1,2,3.@{name="Anna"}[int]$alter = 25. Das macht Sinn bei Funktions-Parametern (siehe L5) und für Klarheit. Den Typ einer Variable abfragen: $alter.GetType().Name oder $alter -is [int]. Konvertierung explizit: [int]"42" macht aus String eine Zahl, [string]42 umgekehrt.3) Strings: Einfache und doppelte Anführungszeichen
Wie in Bash macht es einen Unterschied ob du einfache oder doppelte Anführungszeichen nutzt:
"Property $obj.Name" würde NUR $obj ersetzen, dann „.Name" als Text dranhängen. Um Property-Zugriffe zu interpolieren brauchst du die $()-Subexpression-Syntax: "Property $($obj.Name)". Genauso bei Cmdlet-Aufrufen: "Time: $(Get-Date)". Diese Klammern sind eine der häufigsten Anfängerverwirrungen – merke sie dir.4) Spezielle Variablen
PowerShell hat einige eingebaute Variablen die wichtig zu kennen sind:
| Variable | Inhalt |
|---|---|
$_ oder $PSItem | Das aktuelle Pipeline-Element. Wichtigster Variable überhaupt! |
$null | Der "Nichts"-Wert. Mit -eq $null testen. |
$true, $false | Bool-Werte. |
$env:USERNAME, $env:USERPROFILE | Umgebungsvariablen. $env:PATH wie in Bash. |
$PSVersionTable | Version + Plattform-Info. |
$Error | Array der letzten Fehler. $Error[0] = letzter Fehler. |
$? | True wenn letzter Befehl erfolgreich war. |
$args | Argumente die ans Skript/Funktion übergeben wurden. |
$PSScriptRoot | Verzeichnis der aktuell laufenden .ps1-Datei. |
$Host | Informationen über die Konsole/Host. |
Besonders wichtig zu verstehen: $_. Innerhalb von Where-Object und ForEach-Object referenziert das die Sache, die gerade durch die Pipeline fließt. Mehr in Abschnitt 7.
5) Die Pipeline – das Herzstück
Die Pipeline funktioniert mit dem gleichen |-Operator wie in Bash. Aber der Inhalt ist anders: Objekte fließen durch, nicht Strings. Jedes Cmdlet bekommt Objekte rein, gibt Objekte raus. Das nächste Cmdlet kann direkt auf die Properties zugreifen:
{$_.CPU -gt 100}
CPU -Descending
-First 3
Format-Table) werden sie zu Text gerendert. Du kannst die Pipeline auch in einer Variable festhalten: $top = Get-Process | ... | Select -First 3. Dann ist $top ein Array von 3 Process-Objekten.6) Die wichtigsten Pipeline-Cmdlets
Diese paar Cmdlets brauchst du in JEDER Pipeline. Lerne sie auswendig:
| Cmdlet | Was es macht | Alias |
|---|---|---|
Where-Object | Filtert: nur Objekte mit bestimmter Eigenschaft durch | ? oder where |
ForEach-Object | Aktion pro Objekt ausführen | % oder foreach |
Sort-Object | Sortiert | sort |
Select-Object | Wählt Properties oder bestimmte Objekte | select |
Group-Object | Gruppiert nach Property | group |
Measure-Object | Statistik: Anzahl, Summe, Min/Max/Avg | measure |
Format-Table | Tabellarische Darstellung | ft |
Format-List | Eine Property pro Zeile | fl |
Export-Csv | In CSV-Datei schreiben | — |
ConvertTo-Json | In JSON umwandeln | — |
Diese Cmdlets sind wie ein Werkzeugkasten der zu allem passt: sie funktionieren mit jedem Objekt – Prozessen, Services, Files, AD-Usern, was auch immer. Das Schema „Objekte erzeugen → filtern → sortieren → wählen → ausgeben" ist universell.
7) Where-Object: filtern mit $_
Where-Object ist der Filter-Cmdlet. Es nimmt einen Script-Block { ... } und wendet ihn auf jedes Pipeline-Objekt an. Wenn der Block $true zurückgibt, kommt das Objekt durch:
Get-Service | Where-Object Status -eq Running – ohne $_ und ohne geschweifte Klammern. Das funktioniert für einfache Property-Vergleiche. Bei komplexen Bedingungen mit AND/OR brauchst du die volle Form: Where-Object { $_.Status -eq "Running" -and $_.StartType -eq "Auto" }.8) Operatoren für Vergleiche
Wo wir gerade -eq gesehen haben: PowerShell hat keine Vergleichs-Operatoren mit Sonderzeichen wie ==, !=, >, <. Stattdessen benannte Operatoren – ähnlich zu Bash mit -eq/-lt/-gt:
!"Anna" -eq "anna" → $true. Für strikten Vergleich -ceq nutzen (mit „c" vorne für case-sensitive). Das ist anders als in den meisten Programmiersprachen – aber für interaktiven Admin-Alltag oft praktischer. -like mit Wildcards (*, ?) ist einfacher als Regex – nutze es wenn die Pattern simpel sind. -match mit Regex für komplexere Sachen.9) ForEach-Object: Aktion pro Objekt
Während Where-Object filtert, FÜHRT ForEach-Object Aktionen pro Objekt aus. Der Script-Block bekommt jedes Objekt als $_:
In PowerShell 7+ gibt es einen parallelen Modus für ForEach-Object: -Parallel führt den Block für mehrere Objekte gleichzeitig aus. Riesiger Speedup bei langsamen Operationen wie Web-Requests oder Remote-Befehlen. Aber Vorsicht – innerhalb des parallelen Blocks gelten Scope-Regeln (du musst Variablen mit $using: referenzieren).
10) Select-Object: Properties wählen oder Slice nehmen
Select-Object hat zwei Hauptaufgaben: bestimmte Properties auswählen, oder eine bestimmte Anzahl Objekte nehmen:
Besonders nützlich: -ExpandProperty. Manchmal willst du nur die rohen Werte einer Property – nicht Objekte die diese Property haben. Beispiel: Get-Service | Select-Object -ExpandProperty Name liefert eine Liste von Strings (Service-Namen), die du dann z.B. an andere Cmdlets weitergeben kannst.
11) Property-Zugriff vs. Methoden-Aufruf
Objekte haben Properties (Daten) und Methoden (Funktionen, die was tun). Beide greifst du mit dem Punkt zu:
Get-Member (kurz: gm) ist Gold wert beim Erkunden unbekannter Objekte. Sobald du nicht weißt was ein Objekt kann: $obj | Get-Member. Listet alle Properties (mit Datentyp) und Methoden (mit Signatur). Das ist die Selbsthilfe auf Objekt-Ebene.
12) Ausgabe: Format-Table, Format-List, Export-Csv
Standardmäßig zeigt PowerShell Objekte als Tabelle. Aber du hast Kontrolle:
Wichtiger Hinweis: Format-* sollte das ENDE der Pipeline sein. Format-Cmdlets erzeugen spezielle „FormatInfo"-Objekte die für die Darstellung gedacht sind – wenn du danach noch Where-Object oder Export-Csv hängst, geht das schief. Faustregel: erst alle Filter/Sort/Select, dann Format-* zur Anzeige. Wenn du in Datei willst: Export-Csv oder Out-File direkt, ohne vorheriges Format.
13) Klassische Stolperfallen
Drei häufige Anfänger-Fehler:
$obj.Propertyin String-Interpolation:"Hallo $user.Name"ergibt nicht „Hallo Anna" sondern „Hallo <User-Object>.Name". Richtig:"Hallo $($user.Name)"mit Subexpression-Klammern.=statt-eqin Where-Object:Where-Object { $_.Status = "Running" }weist zu statt zu vergleichen! Korrekt:-eq.- Format-* mitten in der Pipeline:
... | Format-Table | Where-Object ...filtert auf FormatInfo-Objekten, nicht den Original-Daten. Format immer zuletzt.
Zusammenfassung
Variablen mit $name = wert, Leerzeichen um = erlaubt. Echte Datentypen: [string], [int], [double], [bool], [datetime], [array], [hashtable]. "..." interpoliert, '...' literal. Property-Interpolation mit "$($obj.Prop)". $_ = aktuelles Pipeline-Element. Pipeline transportiert Objekte (nicht Text!) – Get-* erzeugt, Where/Sort/Select verarbeiten, Format/Export gibt aus. Wichtigste Pipeline-Cmdlets: Where-Object (filter, Alias ?), ForEach-Object (Aktion, Alias %), Sort-Object, Select-Object (Properties oder -First/-Last), Group-Object, Measure-Object. Operatoren: -eq -ne -lt -le -gt -ge für Vergleich, -like -match -contains für Strings, -and -or -not für Logik. Case-insensitive by default. Get-Member erkundet Objekte. Format-* immer am Pipeline-Ende.
