# Powershell

# Grundlagen



# Thema 0  -  Powershell Wissen

#### **Powershell** 

##### ist eine lose typisierte Programmiersprache und arbeitet mit implizierten Konvertierungen

> Skriptsprache: eine Programmiersprache die für Skripte verwendet wird, arbeitet mit meist nach dem Stapelverarbeitungsmodus und ist meist in interpritiert. (Interpreter)

# Grundlagen - Operatoren

PowerShell – Grundlagen: Operatoren

---

## Überblick

Operatoren in PowerShell werden verwendet für:

- Vergleiche  
- String-Suche  
- Listenprüfungen  
- Berechnungen  
- Zuweisungen  

---

## Vergleichsoperatoren

```powershell
-eq   # gleich (equal)
-ne   # ungleich (not equal)
-gt   # größer als (greater than)
-lt   # kleiner als (less than)
-ge   # größer gleich (greater equal)
-le   # kleiner gleich (less equal)

Clear-Host

"Apfel" -eq "Birne"
"Apfel" -ceq "apfel"   # case sensitive Vergleich

12 -eq 12   # true
12 -ne 15   # true
12 -gt 9    # true
12 -lt 9    # false
12 -ge 11   # true
12 -le 12   # true

"Apfel" -lt "Birne"   # alphabetischer Vergleich

# Grundlagen Zusammenfassung

**Variablen & Strings**

- Variablen starten mit `$` und werden mit `=` gesetzt → `$x = 5` (Typ automatisch)
- Zugriff immer mit `$`
- `"..."` → Variable wird **ersetzt** (ausgewertet) → `"Wert: $x"` → Wert: 5
- `'...'` → Variable bleibt **Text** → `'Wert: $x'` → Wert: $x
- `=` → Zuweisung | Vergleich z. B. mit `-eq`

👉 Merksatz:  
**Doppelte Anführungszeichen = Wert wird eingesetzt**  
**Einfache Anführungszeichen = bleibt nur Text**

---

**Datentypen**

- PowerShell ist **dynamisch typisiert** → Typ wird automatisch erkannt (`$x = 5`, `$y = "Text"`)
- Häufige Typen: String (`"Text"`), Int (`5`), Double (`3.14`), Boolean (`$true/$false`), Array (`1,2,3`)
- Typ kann **explizit gesetzt** werden → `[int]$x = 5`, `[string]$name = "Derick"`
- Typ prüfen → `$x.GetType()`

👉 Wichtig:
- Rechnen nur mit Zahlen sinnvoll (`"5" + 5` → kann unerwartet sein)
- Arrays werden mit Komma erstellt → `$arr = 1,2,3`

👉 Merksatz:  
**Typ kommt automatisch – kann aber festgelegt werden**

---

- Ausgabe →
  - `Write-Host "Text"` (nur Anzeige, nicht weiter nutzbar)
  - `Write-Output "Text"` oder `"Text"` (**empfohlen, weiterverarbeitbar**)
- Eingabe → `$x = Read-Host "Frage"`
- Datum → `Get-Date`
- Konsole löschen → `Clear-Host` / `cls` (beides leert die Konsole)

<details>
<summary>👉 Beispiele anzeigen</summary>

<br>

```powershell
# Ausgabe 'Write-Output'

# Variante 1 (offiziell)
Write-Output "Hallo"   # → Ausgabe: Hallo

# Variante 2 (Kurzform)
"Hallo"                # → Ausgabe: Hallo

# Konsole löschen 'cls'

# Variante 1 (voller Befehl)
Clear-Host             # → Konsole wird geleert

# Variante 2 (Kurzform / Alias)
cls                    # → Konsole wird geleert
```

</details>

<br>

👉 Merksatz:
**Write-Output besser als Write-Host | Read-Host Input einlesen | Cls entspricht Clear-Host**

---

**Rechnen**

* Grundrechenarten → `+` `-` `*` `/`
* Beispiele → `$x = 5 + 3` | `$y = 10 - 2` | `$z = 4 * 2` | `$a = 8 / 2`
* Punkt vor Strich gilt → `$r = 2 + 3 * 4` → Ergebnis: 14
* Klammern steuern Reihenfolge → `$r = (2 + 3) * 4` → Ergebnis: 20
* Zuweisung kombiniert → `$x += 5` (gleich `$x = $x + 5`)
<details>
<summary>👉 Beispiel anzeigen</summary>

<br>

```powershell id="ex01"
# Variante 1 (lang)
$x = $x + 5   # → erhöht $x um 5

# Variante 2 (kurz)
$x += 5       # → erhöht $x um 5
```

</details>


👉 Merksatz:
**Operatoren wie Mathe | Reihenfolge beachten | Klammern nutzen**

---

**Operatoren**

* Vergleich → `-eq` `-ne` `-gt` `-lt` → vergleichen Werte (True/False)
* Rechnen → `+` `-` `*` `/`
* Zuweisung → `=` `+=`
* String → `-like` (Wildcard) | `-match` (Regex)
* Listen → `-contains` (Liste enthält Wert) | `-in` (Wert in Liste)
* Logisch → `-and` `-or` `-not`
* Zusatz → `-not` (verneint) | `-c` (case-sensitive, z. B. `-ceq`)

<details>
<summary>👉 Beispiele anzeigen</summary>

<br>

```powershell
# Vergleich
5 -eq 5        # → True
5 -gt 3        # → True

# Rechnen
2 + 3          # → 5

# Zuweisung
$x = 5
$x += 2        # → 7

# String
"Test" -like "T*"    # → True
"Test" -match "es"   # → True

# Listen
1,2,3 -contains 2    # → True
2 -in 1,2,3          # → True

# Logisch
($true -and $false)  # → False

# Zusatz
5 -ne 3              # → True
"Test" -ceq "test"   # → False (Groß/Klein beachten)
```

</details>

---

**PowerShell Verzweigungen (kurz & knapp)**

* `if / else` → führt Code je nach Bedingung aus
* `switch` → prüft eine Variable gegen mehrere Fälle (übersichtlicher als viele ifs)

<details>
<summary>👉 Beispiele anzeigen</summary>

<br>

```powershell
# if / else
$x = 10

if ($x -gt 5) {
    "größer als 5"
} else {
    "kleiner oder gleich 5"
}

# switch
$farbe = "rot"

switch ($farbe) {
    "rot"   { "Stop" }
    "grün"  { "Go" }
    default { "Unbekannt" }
}
```

</details>

👉 Merksatz:
**if = einfache Entscheidung | switch = viele Fälle übersichtlich**

# PowerShell – Parameter

**Grundidee**

Parameter sind Zusatzangaben zu einem PowerShell-Befehl.

Mit Parametern legt man fest, **was genau ein Cmdlet tun soll** oder **wie es arbeiten soll**.

Ein PowerShell-Befehl besteht meistens aus:

| Bestandteil | Bedeutung |
|---|---|
| Cmdlet | Der eigentliche PowerShell-Befehl |
| Parameter | Zusatzangabe, die das Cmdlet genauer steuert |
| Parameterwert | Der konkrete Wert, der an den Parameter übergeben wird |

Beispiel:

    Get-Process -Name "notepad"

Bedeutung:

| Teil | Erklärung |
|---|---|
| Get-Process | Cmdlet |
| -Name | Parameter |
| "notepad" | Parameterwert |

PowerShell zeigt dadurch nicht alle Prozesse an, sondern nur den Prozess mit dem Namen **notepad**.

---

**Merksatz**

**Cmdlet = Was soll passieren?**  
**Parameter = Wie genau soll es passieren?**  
**Parameterwert = Womit oder worauf soll es passieren?**

---

**Typischer Aufbau**

Ein PowerShell-Befehl mit Parameter hat meistens diesen Aufbau:

    Cmdlet -Parameter Wert

Beispiel:

    Get-Service -Name "Spooler"

Bedeutung:

| Teil | Erklärung |
|---|---|
| Get-Service | Dienste anzeigen |
| -Name | Nach einem bestimmten Dienstnamen suchen |
| "Spooler" | Druckwarteschlange als konkreter Dienst |

---

**Warum Parameter wichtig sind**

Ohne Parameter führt ein Cmdlet oft eine allgemeine Aktion aus.

Beispiel:

    Get-Service

Dieser Befehl zeigt viele Dienste an.

Mit Parameter wird die Ausgabe gezielter:

    Get-Service -Name "Spooler"

Jetzt wird nur der Dienst **Spooler** angezeigt.

Parameter helfen also dabei, Befehle genauer, sicherer und gezielter auszuführen.

---

**Parameter mit Wert**

Viele Parameter benötigen einen Wert.

Beispiel:

    Get-ChildItem -Path "C:\Temp"

Hier braucht der Parameter **-Path** einen konkreten Pfad.

Weitere Beispiele:

    Get-Process -Name "notepad"

    Get-Service -Name "Spooler"

    Get-ChildItem -Filter "*.txt"

Typische Parameter mit Wert:

| Parameter | Bedeutung |
|---|---|
| -Name | Name eines Objekts |
| -Path | Pfad zu Datei oder Ordner |
| -Filter | Filter für Dateien oder Objekte |
| -ComputerName | Zielcomputer |
| -Credential | Zugangsdaten |
| -Destination | Zielpfad |
| -Source | Quellpfad |

---

**Schalterparameter**

Ein Schalterparameter braucht keinen eigenen Wert.

Er ist aktiv, sobald man ihn angibt.

Beispiel:

    Get-ChildItem -Recurse

Der Parameter **-Recurse** bedeutet, dass auch Unterordner durchsucht werden.

Weitere Beispiele:

    Remove-Item "C:\Temp\test.txt" -Force

    Get-ChildItem -Hidden

    Stop-Process -Name "notepad" -Force

Typische Schalterparameter:

| Parameter | Bedeutung |
|---|---|
| -Recurse | Unterordner einbeziehen |
| -Force | Aktion erzwingen |
| -Hidden | Versteckte Elemente anzeigen |
| -WhatIf | Zeigt, was passieren würde, ohne es auszuführen |
| -Confirm | Fragt vor der Ausführung nach Bestätigung |

---

**Wichtige Sicherheitsparameter**

Besonders wichtig sind **-WhatIf** und **-Confirm**.

Diese Parameter helfen, gefährliche Aktionen zu prüfen.

Beispiel:

    Remove-Item "C:\Temp\test.txt" -WhatIf

PowerShell zeigt nur an, was gelöscht werden würde.  
Die Datei wird nicht wirklich gelöscht.

Beispiel mit Bestätigung:

    Remove-Item "C:\Temp\test.txt" -Confirm

PowerShell fragt vor dem Löschen nach.

Das ist besonders wichtig bei Befehlen wie:

| Cmdlet | Risiko |
|---|---|
| Remove-Item | Dateien oder Ordner löschen |
| Stop-Process | Prozesse beenden |
| Restart-Computer | Computer neu starten |
| Set-Item | Werte ändern |
| New-Item | Neue Dateien, Ordner oder Einträge erstellen |

---

**Positionelle Parameter**

Manche Parameter müssen nicht ausgeschrieben werden, weil PowerShell anhand der Position erkennt, welcher Parameter gemeint ist.

Beispiel mit ausgeschriebenem Parameter:

    Get-ChildItem -Path "C:\Temp"

Kurzform:

    Get-ChildItem "C:\Temp"

PowerShell erkennt hier, dass **"C:\Temp"** der Wert für **-Path** ist.

Für die Prüfung und für saubere Dokumentation ist die ausgeschriebene Variante besser:

    Get-ChildItem -Path "C:\Temp"

Sie ist klarer und leichter nachvollziehbar.

---

**Mehrere Parameter kombinieren**

Ein Cmdlet kann mehrere Parameter gleichzeitig verwenden.

Beispiel:

    Get-ChildItem -Path "C:\Temp" -Filter "*.txt" -Recurse

Bedeutung:

| Teil | Erklärung |
|---|---|
| Get-ChildItem | Ordnerinhalt anzeigen |
| -Path "C:\Temp" | Im Ordner C:\Temp suchen |
| -Filter "*.txt" | Nur Textdateien anzeigen |
| -Recurse | Auch Unterordner durchsuchen |

Der Befehl sucht also im Ordner **C:\Temp** und allen Unterordnern nach Dateien mit der Endung **.txt**.

---

**Parameter und Datentypen**

Parameter erwarten oft bestimmte Datentypen.

Beispiele:

| Datentyp | Beispiel | Bedeutung |
|---|---|---|
| String | "notepad" | Text |
| Integer | 10 | Ganze Zahl |
| Boolean | $true / $false | Wahr oder falsch |
| Array | "PC1","PC2","PC3" | Mehrere Werte |
| Credential | Benutzername/Kennwort | Zugangsdaten |
| Switch | -Force | Schalterparameter ohne Wert |

Beispiel mit mehreren Namen:

    Get-Service -Name "Spooler","WinRM"

Hier bekommt der Parameter **-Name** mehrere Werte.

---

**Parameter und Anführungszeichen**

Texte mit Leerzeichen sollten in Anführungszeichen geschrieben werden.

Beispiel:

    Get-ChildItem -Path "C:\Meine Dateien"

Ohne Anführungszeichen könnte PowerShell den Pfad falsch interpretieren.

Bei einfachen Werten ohne Leerzeichen sind Anführungszeichen oft nicht zwingend nötig:

    Get-Service -Name Spooler

Trotzdem ist es beim Lernen oft übersichtlicher, Zeichenketten mit Anführungszeichen zu schreiben.

---

**Parameter mit Wildcards**

Viele Parameter unterstützen Platzhalterzeichen.

Das wichtigste Platzhalterzeichen ist:

| Zeichen | Bedeutung |
|---|---|
| * | Steht für beliebig viele Zeichen |
| ? | Steht für genau ein Zeichen |

Beispiel:

    Get-Service -Name "Win*"

Zeigt Dienste an, deren Name mit **Win** beginnt.

Beispiel:

    Get-ChildItem -Path "C:\Temp" -Filter "*.txt"

Zeigt alle Dateien mit der Endung **.txt** an.

---

**Pflichtparameter**

Manche Parameter sind erforderlich.

Wenn ein Pflichtparameter fehlt, fragt PowerShell nach dem fehlenden Wert.

Beispiel:

    Read-Host -Prompt

PowerShell erwartet hier einen Wert für **-Prompt**.

Besser:

    Read-Host -Prompt "Bitte Namen eingeben"

---

**Optionale Parameter**

Viele Parameter sind optional.

Beispiel:

    Get-Process

Dieser Befehl funktioniert ohne weitere Parameter.

Mit optionalem Parameter wird er genauer:

    Get-Process -Name "notepad"

Der Parameter **-Name** ist hier nicht zwingend notwendig, aber nützlich.

---

**Parameter und Pipeline**

PowerShell arbeitet objektorientiert.  
Die Pipeline übergibt nicht nur Text, sondern Objekte von einem Befehl zum nächsten.

Beispiel:

    Get-Process -Name "notepad" | Stop-Process

Bedeutung:

| Teil | Erklärung |
|---|---|
| Get-Process -Name "notepad" | Sucht den Prozess notepad |
| Pipe-Zeichen | Übergibt das gefundene Objekt weiter |
| Stop-Process | Beendet den übergebenen Prozess |

Noch deutlicher:

    Get-Process -Name "notepad" | Stop-Process -Force

Hier beendet PowerShell den Prozess **notepad** erzwungen.

---

**Pipeline-Parameter**

Einige Parameter können Werte aus der Pipeline annehmen.

Beispiel:

    Get-Service -Name "Spooler" | Stop-Service

Der Dienst wird zuerst gesucht und dann an **Stop-Service** weitergegeben.

PowerShell erkennt anhand des Objekttyps, welcher Parameter des nächsten Cmdlets den Wert annehmen kann.

Das nennt man auch:

| Begriff | Bedeutung |
|---|---|
| Pipeline Input | Eingabe aus der Pipeline |
| ByValue | Übergabe anhand des Objekttyps |
| ByPropertyName | Übergabe anhand eines passenden Eigenschaftsnamens |

Für die IHK reicht meistens das Grundverständnis:

**Die Pipeline übergibt das Ergebnis eines Befehls an den nächsten Befehl. Parameter können diese übergebenen Werte weiterverarbeiten.**

---

**Common Parameters**

Viele PowerShell-Cmdlets besitzen gemeinsame Standardparameter.

Diese nennt man **Common Parameters**.

Wichtige Beispiele:

| Parameter | Bedeutung |
|---|---|
| -Verbose | Gibt ausführlichere Informationen aus |
| -Debug | Gibt Debug-Informationen aus |
| -ErrorAction | Legt fest, wie Fehler behandelt werden |
| -ErrorVariable | Speichert Fehler in einer Variable |
| -WarningAction | Legt fest, wie Warnungen behandelt werden |
| -OutVariable | Speichert die Ausgabe in einer Variable |
| -PipelineVariable | Speichert Pipeline-Objekte in einer Variable |

Beispiel:

    Get-Service -Name "Spooler" -Verbose

Mit **-Verbose** können zusätzliche Informationen angezeigt werden.

---

**Fehlerbehandlung mit Parametern**

Ein wichtiger Parameter ist **-ErrorAction**.

Damit legt man fest, wie PowerShell bei Fehlern reagieren soll.

Beispiel:

    Get-Item -Path "C:\NichtVorhanden" -ErrorAction SilentlyContinue

Bedeutung:

PowerShell gibt keinen sichtbaren Fehler aus, wenn der Pfad nicht existiert.

Häufige Werte für **-ErrorAction**:

| Wert | Bedeutung |
|---|---|
| Continue | Fehler anzeigen und weitermachen |
| Stop | Fehler anzeigen und Ausführung stoppen |
| SilentlyContinue | Fehler nicht anzeigen und weitermachen |
| Inquire | Nachfrage anzeigen |
| Ignore | Fehler ignorieren |

---

**Parameter herausfinden**

Man muss nicht alle Parameter auswendig kennen.

PowerShell bietet Hilfe-Befehle.

Wichtige Befehle:

    Get-Help Get-ChildItem

Zeigt Hilfe zum Cmdlet an.

    Get-Help Get-ChildItem -Detailed

Zeigt ausführlichere Informationen.

    Get-Help Get-ChildItem -Examples

Zeigt Beispiele.

    Get-Command Get-ChildItem -Syntax

Zeigt die Syntax des Cmdlets.

    Get-Command Get-ChildItem | Select-Object -ExpandProperty Parameters

Zeigt die verfügbaren Parameter eines Cmdlets.

---

**Syntax in der Hilfe verstehen**

Bei PowerShell-Hilfeausgaben sieht man oft eckige Klammern.

Beispiel:

    Get-ChildItem [[-Path] <string[]>] [-Filter <string>] [-Recurse]

Bedeutung:

| Schreibweise | Bedeutung |
|---|---|
| [-Path] | Parameter ist optional |
| <string[]> | Erwartet einen oder mehrere Textwerte |
| [-Filter <string>] | Optionaler Parameter mit Textwert |
| [-Recurse] | Optionaler Schalterparameter |

Wichtig:

Eckige Klammern bedeuten in der Syntax meistens: **optional**.

---

**Cmdlet-Namen und Parameter**

PowerShell-Cmdlets folgen meistens dem Verb-Nomen-Schema.

Beispiele:

| Cmdlet | Bedeutung |
|---|---|
| Get-Process | Prozesse abrufen |
| Stop-Process | Prozess beenden |
| Get-Service | Dienste abrufen |
| Start-Service | Dienst starten |
| Stop-Service | Dienst stoppen |
| Get-ChildItem | Ordnerinhalt anzeigen |
| Remove-Item | Datei/Ordner löschen |
| New-Item | Datei/Ordner erstellen |
| Copy-Item | Datei/Ordner kopieren |
| Move-Item | Datei/Ordner verschieben |

Parameter passen sich an das jeweilige Cmdlet an.

Beispiel:

    Get-Service -Name "Spooler"

    Stop-Service -Name "Spooler"

Beide Befehle nutzen **-Name**, aber mit unterschiedlicher Aktion.

---

**Aliase und Parameter**

PowerShell besitzt auch Kurzformen, sogenannte Aliase.

Beispiele:

| Alias | Eigentliches Cmdlet |
|---|---|
| dir | Get-ChildItem |
| ls | Get-ChildItem |
| cd | Set-Location |
| copy | Copy-Item |
| del | Remove-Item |
| cat | Get-Content |

Beispiel:

    dir "C:\Temp"

Das entspricht ungefähr:

    Get-ChildItem -Path "C:\Temp"

Für die IHK und Dokumentation ist das ausgeschriebene Cmdlet besser, weil es eindeutiger ist.

---

**Parameter in eigenen Skripten**

Auch eigene PowerShell-Skripte können Parameter besitzen.

Beispiel:

    param(
        [string]$Name
    )

    Write-Output "Hallo $Name"

Wenn das Skript zum Beispiel **gruss.ps1** heißt, kann man es so starten:

    .\gruss.ps1 -Name "Felix"

Ausgabe:

    Hallo Felix

---

**Mehrere eigene Parameter**

Beispiel:

    param(
        [string]$Name,
        [int]$Alter
    )

    Write-Output "$Name ist $Alter Jahre alt."

Aufruf:

    .\person.ps1 -Name "Felix" -Alter 30

Hier sind:

| Teil | Bedeutung |
|---|---|
| -Name | Parameter für den Namen |
| "Felix" | Wert für den Namen |
| -Alter | Parameter für das Alter |
| 30 | Wert für das Alter |

---

**Pflichtparameter in eigenen Skripten**

Man kann Parameter als verpflichtend kennzeichnen.

Beispiel:

    param(
        [Parameter(Mandatory=$true)]
        [string]$Name
    )

    Write-Output "Hallo $Name"

Wenn der Parameter **-Name** beim Start fehlt, fragt PowerShell nach.

---

**Parameter mit Standardwert**

Parameter können Standardwerte besitzen.

Beispiel:

    param(
        [string]$Name = "Benutzer"
    )

    Write-Output "Hallo $Name"

Wenn kein Name angegeben wird, verwendet PowerShell automatisch **Benutzer**.

---

**Parameter validieren**

PowerShell kann Parameterwerte prüfen.

Beispiel mit erlaubten Werten:

    param(
        [ValidateSet("Start","Stop","Restart")]
        [string]$Aktion
    )

    Write-Output "Gewählte Aktion: $Aktion"

Jetzt darf der Parameter **-Aktion** nur bestimmte Werte annehmen:

| Erlaubter Wert |
|---|
| Start |
| Stop |
| Restart |

Beispiel:

    .\dienst.ps1 -Aktion Start

Ein falscher Wert würde abgelehnt werden.

---

**Typische IHK-relevante Beispiele**

**Dienst anzeigen**

    Get-Service -Name "Spooler"

Zeigt den Dienst **Spooler** an.

---

**Dienst starten**

    Start-Service -Name "Spooler"

Startet den Dienst **Spooler**.

---

**Dienst stoppen**

    Stop-Service -Name "Spooler"

Stoppt den Dienst **Spooler**.

---

**Prozess anzeigen**

    Get-Process -Name "notepad"

Zeigt den Prozess **notepad** an.

---

**Prozess beenden**

    Stop-Process -Name "notepad"

Beendet den Prozess **notepad**.

---

**Dateien in einem Ordner anzeigen**

    Get-ChildItem -Path "C:\Temp"

Zeigt den Inhalt des Ordners **C:\Temp** an.

---

**Dateien rekursiv suchen**

    Get-ChildItem -Path "C:\Temp" -Filter "*.log" -Recurse

Sucht im Ordner **C:\Temp** und allen Unterordnern nach **.log-Dateien**.

---

**Datei löschen mit Sicherheitsprüfung**

    Remove-Item -Path "C:\Temp\test.txt" -WhatIf

Zeigt an, was gelöscht werden würde, löscht aber nicht wirklich.

---

**Datei löschen mit Bestätigung**

    Remove-Item -Path "C:\Temp\test.txt" -Confirm

Fragt vor dem Löschen nach.

---

**Wichtige Begriffe**

| Begriff | Erklärung |
|---|---|
| Cmdlet | PowerShell-Befehl im Verb-Nomen-Schema |
| Parameter | Zusatzangabe zu einem Cmdlet |
| Parameterwert | Konkreter Wert zu einem Parameter |
| Schalterparameter | Parameter ohne eigenen Wert |
| Pflichtparameter | Muss angegeben werden |
| Optionaler Parameter | Kann angegeben werden, muss aber nicht |
| Positioneller Parameter | Kann ohne Parameternamen verwendet werden |
| Pipeline | Übergibt Objekte von einem Befehl zum nächsten |
| Common Parameters | Gemeinsame Standardparameter vieler Cmdlets |
| Alias | Kurzname für ein Cmdlet |

---

**Häufige Fehler**

| Fehler | Erklärung |
|---|---|
| Parameter falsch geschrieben | PowerShell erkennt den Parameter nicht |
| Wert fehlt | Ein Parameter erwartet einen Wert |
| Falscher Datentyp | Zum Beispiel Text statt Zahl |
| Pfad ohne Anführungszeichen | Fehler bei Leerzeichen im Pfad möglich |
| Zu gefährlicher Befehl ohne -WhatIf | Aktion wird direkt ausgeführt |
| Alias statt Cmdlet in Dokumentation | Kann unklar oder weniger professionell wirken |

---

**Gute Praxis**

| Empfehlung | Grund |
|---|---|
| Parameter ausschreiben | Bessere Lesbarkeit |
| Cmdlets statt Aliase verwenden | Eindeutiger und professioneller |
| Bei gefährlichen Befehlen -WhatIf nutzen | Verhindert versehentliche Änderungen |
| Pfade mit Leerzeichen in Anführungszeichen setzen | Vermeidet Fehler |
| Get-Help nutzen | Parameter müssen nicht auswendig gelernt werden |
| Befehle erst testen | Besonders bei Löschen, Stoppen oder Ändern |

---

**IHK-Einordnung**

Für die IHK ist vor allem wichtig, dass man das Prinzip versteht.

Man muss normalerweise nicht jeden Parameter auswendig kennen.

Wichtig ist:

| Prüfungsrelevanter Punkt | Erklärung |
|---|---|
| Cmdlet erkennen | PowerShell-Befehl verstehen |
| Parameter erkennen | Zusatzangabe zum Befehl erkennen |
| Parameterwert erkennen | Konkreten Wert zuordnen |
| Schalterparameter verstehen | Parameter ohne eigenen Wert |
| Pipeline verstehen | Ausgabe eines Befehls wird weitergegeben |
| Sichere Ausführung verstehen | -WhatIf und -Confirm kennen |
| Hilfe verwenden können | Get-Help und Get-Command kennen |

---

**Prüfungsnahes Beispiel**

Aufgabe:

Ein Administrator möchte alle Textdateien im Ordner **C:\Temp** und dessen Unterordnern anzeigen lassen.

Passender PowerShell-Befehl:

    Get-ChildItem -Path "C:\Temp" -Filter "*.txt" -Recurse

Erklärung:

| Teil | Bedeutung |
|---|---|
| Get-ChildItem | Ordnerinhalt anzeigen |
| -Path "C:\Temp" | Startordner festlegen |
| -Filter "*.txt" | Nur Textdateien anzeigen |
| -Recurse | Unterordner einbeziehen |

---

**Prüfungsnahes Beispiel mit Sicherheit**

Aufgabe:

Ein Administrator möchte prüfen, welche Dateien durch einen Löschbefehl betroffen wären, ohne sie wirklich zu löschen.

Passender PowerShell-Befehl:

    Remove-Item -Path "C:\Temp\*.log" -WhatIf

Erklärung:

| Teil | Bedeutung |
|---|---|
| Remove-Item | Elemente löschen |
| -Path "C:\Temp\*.log" | Alle .log-Dateien im Zielpfad |
| -WhatIf | Nur anzeigen, was passieren würde |

---

**Zusammenfassung**

Parameter sind ein zentrales Konzept in PowerShell.

Sie steuern, wie ein Cmdlet arbeitet und auf welche Objekte es angewendet wird.

Die wichtigsten Punkte:

| Punkt | Kurz erklärt |
|---|---|
| Parameter steuern Cmdlets | Sie machen Befehle genauer |
| Manche Parameter brauchen Werte | Zum Beispiel -Name "Spooler" |
| Schalterparameter brauchen keinen Wert | Zum Beispiel -Recurse oder -Force |
| Parameter können kombiniert werden | Dadurch entstehen gezielte Befehle |
| -WhatIf und -Confirm erhöhen die Sicherheit | Besonders bei gefährlichen Aktionen |
| Get-Help zeigt verfügbare Parameter | Man muss nicht alles auswendig kennen |
| Die Pipeline übergibt Objekte weiter | Cmdlets können miteinander kombiniert werden |

---

**Kurzer Merksatz**

**Ein Parameter ist eine Zusatzangabe zu einem PowerShell-Cmdlet, mit der festgelegt wird, worauf und wie der Befehl angewendet wird.**

**Beispiel:**

    Get-Service -Name "Spooler"

**Get-Service** ist das Cmdlet.  
**-Name** ist der Parameter.  
**"Spooler"** ist der Parameterwert.

# PowerShell – Eigene Parameter definieren

Neben der Verwendung vorhandener Parameter kann man in PowerShell auch eigene Parameter für Skripte und Funktionen definieren.

Dadurch muss man Werte nicht fest im Skript eintragen, sondern kann sie beim Start des Skripts übergeben.

---

**Warum eigene Parameter sinnvoll sind**

Ohne Parameter wären Werte oft fest im Skript eingetragen.

Beispiel ohne Parameter:

    $Name = "Felix"
    Write-Output "Hallo $Name"

Das Problem:

Der Name ist fest im Skript eingetragen.  
Wenn ein anderer Name verwendet werden soll, muss das Skript geändert werden.

Besser ist ein Parameter:

    param(
        [string]$Name
    )

    Write-Output "Hallo $Name"

Aufruf:

    .\gruss.ps1 -Name "Felix"

Ausgabe:

    Hallo Felix

---

**Der param()-Block**

Eigene Parameter werden in PowerShell meistens mit einem `param()`-Block definiert.

Der `param()`-Block steht in Skripten normalerweise am Anfang der Datei.

Grundform:

    param(
        [Datentyp]$Parametername
    )

Beispiel:

    param(
        [string]$Name
    )

    Write-Output "Hallo $Name"

Bedeutung:

| Teil | Erklärung |
|---|---|
| param() | Bereich, in dem Parameter definiert werden |
| [string] | Datentyp des Parameters |
| $Name | Name des Parameters als Variable |

---

**Parameter beim Skriptstart übergeben**

Ein Skript mit Parameter kann beim Start Werte annehmen.

Beispielskript:

    param(
        [string]$Name,
        [int]$Alter
    )

    Write-Output "$Name ist $Alter Jahre alt."

Aufruf:

    .\person.ps1 -Name "Felix" -Alter 30

Bedeutung:

| Teil | Erklärung |
|---|---|
| .\person.ps1 | Skript wird gestartet |
| -Name | Parametername |
| "Felix" | Wert für den Parameter Name |
| -Alter | Parametername |
| 30 | Wert für den Parameter Alter |

---

**Datentypen bei Parametern**

Man kann festlegen, welchen Datentyp ein Parameter erwartet.

Beispiele:

| Datentyp | Bedeutung | Beispiel |
|---|---|---|
| [string] | Text | "Felix" |
| [int] | Ganze Zahl | 30 |
| [bool] | Wahr/Falsch | $true |
| [string[]] | Mehrere Texte | "PC1","PC2" |
| [switch] | Schalterparameter | -VerboseMode |

Beispiel:

    param(
        [string]$ComputerName,
        [int]$Port
    )

    Write-Output "Computer: $ComputerName"
    Write-Output "Port: $Port"

Aufruf:

    .\test.ps1 -ComputerName "Server01" -Port 443

---

**Parameter mit Standardwert**

Ein Parameter kann einen Standardwert haben.

Wenn beim Aufruf kein Wert angegeben wird, verwendet PowerShell automatisch den Standardwert.

Beispiel:

    param(
        [string]$Name = "Benutzer"
    )

    Write-Output "Hallo $Name"

Aufruf ohne Parameter:

    .\gruss.ps1

Ausgabe:

    Hallo Benutzer

Aufruf mit Parameter:

    .\gruss.ps1 -Name "Felix"

Ausgabe:

    Hallo Felix

---

**Pflichtparameter**

Ein Parameter kann verpflichtend gemacht werden.

Dafür verwendet man das Attribut:

    [Parameter(Mandatory)]

Beispiel:

    param(
        [Parameter(Mandatory)]
        [string]$Name
    )

    Write-Output "Hallo $Name"

Wenn der Parameter beim Aufruf fehlt, fragt PowerShell nach dem Wert.

Aufruf:

    .\gruss.ps1

PowerShell fragt dann nach dem fehlenden Parameter.

---

**Parameter-Attribut**

Mit `[Parameter()]` kann man Eigenschaften eines Parameters festlegen.

Beispiel:

    param(
        [Parameter(Mandatory)]
        [string]$ComputerName
    )

Wichtige Eigenschaften:

| Eigenschaft | Bedeutung |
|---|---|
| Mandatory | Parameter ist verpflichtend |
| Position | Parameter kann über seine Position erkannt werden |
| ValueFromPipeline | Wert kann aus der Pipeline kommen |
| ValueFromPipelineByPropertyName | Wert kann über passenden Eigenschaftsnamen aus der Pipeline kommen |
| HelpMessage | Hilfetext für den Parameter |

---

**Positionelle Parameter**

Parameter können auch über ihre Position übergeben werden.

Beispiel:

    param(
        [Parameter(Position=0)]
        [string]$Name,

        [Parameter(Position=1)]
        [int]$Alter
    )

    Write-Output "$Name ist $Alter Jahre alt."

Aufruf mit Parameternamen:

    .\person.ps1 -Name "Felix" -Alter 30

Aufruf über Position:

    .\person.ps1 "Felix" 30

PowerShell erkennt:

| Position | Wert | Parameter |
|---|---|---|
| 0 | "Felix" | Name |
| 1 | 30 | Alter |

Für saubere Dokumentation ist die Variante mit Parameternamen meist besser.

---

**Parameter validieren**

Parameterwerte können geprüft werden.

Dadurch kann verhindert werden, dass falsche Werte verarbeitet werden.

---

**ValidateSet**

Mit `ValidateSet` kann man erlaubte Werte festlegen.

Beispiel:

    param(
        [ValidateSet("Start","Stop","Restart")]
        [string]$Action
    )

    Write-Output "Gewählte Aktion: $Action"

Erlaubte Aufrufe:

    .\dienst.ps1 -Action Start

    .\dienst.ps1 -Action Stop

    .\dienst.ps1 -Action Restart

Nicht erlaubt:

    .\dienst.ps1 -Action Delete

PowerShell würde den falschen Wert ablehnen.

---

**ValidateNotNullOrEmpty**

Mit `ValidateNotNullOrEmpty` wird verhindert, dass ein leerer Wert übergeben wird.

Beispiel:

    param(
        [ValidateNotNullOrEmpty()]
        [string]$Name
    )

    Write-Output "Hallo $Name"

Das ist sinnvoll, wenn ein Parameter zwar angegeben wird, aber nicht leer sein darf.

---

**Schalterparameter selbst definieren**

Schalterparameter werden mit `[switch]` definiert.

Ein Schalterparameter braucht keinen eigenen Wert.

Beispiel:

    param(
        [switch]$Ausfuehrlich
    )

    if ($Ausfuehrlich) {
        Write-Output "Ausführliche Ausgabe aktiviert"
    } else {
        Write-Output "Normale Ausgabe"
    }

Aufruf ohne Schalter:

    .\test.ps1

Aufruf mit Schalter:

    .\test.ps1 -Ausfuehrlich

Bedeutung:

Der Parameter ist aktiv, sobald er angegeben wird.

---

**Parameter in Funktionen**

Parameter können nicht nur in Skripten, sondern auch in Funktionen verwendet werden.

Beispiel:

    function Begruessung {
        param(
            [string]$Name
        )

        Write-Output "Hallo $Name"
    }

Aufruf:

    Begruessung -Name "Felix"

Ausgabe:

    Hallo Felix

---

**Erweiterte Funktion mit Parametern**

Eine etwas sauberere Funktion:

    function Test-Verbindung {
        param(
            [Parameter(Mandatory)]
            [string]$ComputerName
        )

        Test-Connection -ComputerName $ComputerName -Count 2
    }

Aufruf:

    Test-Verbindung -ComputerName "server01"

Hier nimmt die eigene Funktion den Parameter `-ComputerName` entgegen und verwendet ihn intern für `Test-Connection`.

---

**Unbenannte Parameter mit $args**

PowerShell kann auch über `$args` Werte entgegennehmen.

Beispiel:

    Write-Output "Erster Wert: $($args[0])"
    Write-Output "Zweiter Wert: $($args[1])"

Aufruf:

    .\test.ps1 Felix Berlin

Ausgabe:

    Erster Wert: Felix
    Zweiter Wert: Berlin

Das funktioniert, ist aber weniger sauber als ein richtiger `param()`-Block.

Besser:

    param(
        [string]$Name,
        [string]$Ort
    )

    Write-Output "$Name aus $Ort"

Aufruf:

    .\test.ps1 -Name "Felix" -Ort "Berlin"

---

**Named Parameters vs. Positional Parameters**

Es gibt zwei typische Arten, Parameter zu übergeben.

| Art | Beispiel | Erklärung |
|---|---|---|
| Named Parameter | .\test.ps1 -Name "Felix" | Parametername wird angegeben |
| Positional Parameter | .\test.ps1 "Felix" | PowerShell erkennt den Parameter über die Position |

Named Parameters sind besser lesbar und weniger fehleranfällig.

---

**Mehrere Werte übergeben**

Ein Parameter kann mehrere Werte annehmen, wenn er als Array definiert ist.

Beispiel:

    param(
        [string[]]$ComputerName
    )

    foreach ($Computer in $ComputerName) {
        Write-Output "Prüfe $Computer"
    }

Aufruf:

    .\check.ps1 -ComputerName "PC1","PC2","PC3"

Ausgabe:

    Prüfe PC1
    Prüfe PC2
    Prüfe PC3

---

**Advanced Function und CmdletBinding**

Mit `[CmdletBinding()]` kann eine Funktion sich stärker wie ein echtes Cmdlet verhalten.

Beispiel:

    function Remove-TestDatei {
        [CmdletBinding(SupportsShouldProcess)]
        param(
            [Parameter(Mandatory)]
            [string]$Path
        )

        if ($PSCmdlet.ShouldProcess($Path, "Datei löschen")) {
            Remove-Item -Path $Path
        }
    }

Vorteil:

Die Funktion unterstützt dadurch zum Beispiel `-WhatIf`.

Aufruf:

    Remove-TestDatei -Path "C:\Temp\test.txt" -WhatIf

PowerShell zeigt dann nur an, was passieren würde.

Das ist besonders wichtig bei Funktionen, die etwas verändern oder löschen.

---

**Warum Parameter besser sind als feste Werte**

Schlechter Stil:

    $ComputerName = "Server01"
    Test-Connection -ComputerName $ComputerName

Besser:

    param(
        [string]$ComputerName
    )

    Test-Connection -ComputerName $ComputerName

Aufruf:

    .\ping.ps1 -ComputerName "Server01"

Vorteile:

| Vorteil | Erklärung |
|---|---|
| Wiederverwendbar | Skript funktioniert mit verschiedenen Werten |
| Flexibler | Werte werden beim Start übergeben |
| Wartbarer | Skript muss nicht ständig geändert werden |
| Sicherer | Werte können validiert werden |
| Professioneller | Entspricht eher echter Administration |

---

**IHK-Einordnung**

Für die IHK ist vor allem wichtig, das Prinzip zu verstehen:

Ein Parameter macht Skripte und Funktionen flexibel.

Man schreibt nicht alle Werte fest in den Code, sondern übergibt sie beim Aufruf.

Wichtige Punkte:

| Punkt | Bedeutung |
|---|---|
| param() | Definiert eigene Parameter |
| [string], [int], [switch] | Legt Datentypen fest |
| Mandatory | Macht Parameter verpflichtend |
| Position | Erlaubt positionelle Übergabe |
| ValidateSet | Beschränkt erlaubte Werte |
| ValidateNotNullOrEmpty | Verhindert leere Werte |
| [switch] | Erstellt Schalterparameter |
| $args | Enthält unbenannte Argumente |
| CmdletBinding | Macht Funktionen cmdletähnlicher |

---

**Prüfungsnahes Beispiel**

Aufgabe:

Ein Skript soll einen Computernamen als Parameter entgegennehmen und eine Verbindung prüfen.

Lösung:

    param(
        [Parameter(Mandatory)]
        [string]$ComputerName
    )

    Test-Connection -ComputerName $ComputerName -Count 2

Aufruf:

    .\check.ps1 -ComputerName "Server01"

Erklärung:

| Teil | Bedeutung |
|---|---|
| param() | Definiert Eingabeparameter |
| [Parameter(Mandatory)] | Parameter ist verpflichtend |
| [string] | Erwartet Text |
| $ComputerName | Variable für den übergebenen Wert |
| Test-Connection | Prüft Netzwerkverbindung |
| -ComputerName $ComputerName | Nutzt den übergebenen Wert |

---

**Kurzer Merksatz**

**Mit `param()` definiert man eigene Parameter für PowerShell-Skripte oder Funktionen. Dadurch werden Skripte flexibel, wiederverwendbar und professioneller.**

# Powershell Trainer



# Trainer 01 – Basics bis Schleifen

<p>
  <a href="https://trainer.ulrich-wiki.com/powershell-trainer-01-basics-loops.html?v=1" target="_blank" rel="noopener" style="display:inline-block;background:#38bdf8;color:#020617;padding:10px 14px;border-radius:10px;font-weight:700;text-decoration:none;">
    PowerShell-Trainer im Vollbild öffnen
  </a>
</p>

<iframe
  src="https://trainer.ulrich-wiki.com/powershell-trainer-01-basics-loops.html?v=1"
  style="width:100%;height:900px;border:0;border-radius:12px;"
  loading="lazy"
  referrerpolicy="no-referrer-when-downgrade">
</iframe>

# Trainer 02 – Grundlagen

<p>
  <a href="https://trainer.ulrich-wiki.com/powershell-trainer-02-grundlagen.html?v=1" target="_blank" rel="noopener" style="display:inline-block;background:#38bdf8;color:#020617;padding:10px 14px;border-radius:10px;font-weight:700;text-decoration:none;">
    PowerShell-Trainer 02 im Vollbild öffnen
  </a>
</p>

<iframe
  src="https://trainer.ulrich-wiki.com/powershell-trainer-02-grundlagen.html?v=1"
  style="width:100%;height:950px;border:0;border-radius:12px;"
  loading="lazy"
  referrerpolicy="no-referrer-when-downgrade">
</iframe>

# Trainer 03 – Bedingungen und Schleifen

<p>
  <a href="https://trainer.ulrich-wiki.com/powershell-trainer-03-bedingungen-schleifen.html?v=1" target="_blank" rel="noopener" style="display:inline-block;background:#38bdf8;color:#020617;padding:10px 14px;border-radius:10px;font-weight:700;text-decoration:none;">
    PowerShell-Trainer 03 im Vollbild öffnen
  </a>
</p>

<iframe
  src="https://trainer.ulrich-wiki.com/powershell-trainer-03-bedingungen-schleifen.html?v=1"
  style="width:100%;height:1000px;border:0;border-radius:12px;"
  loading="lazy"
  referrerpolicy="no-referrer-when-downgrade">
</iframe>

# Trainer 04 - Schleifen

<p>
  <a href="https://trainer.ulrich-wiki.com/powershell-schleifen-trainer-01.html?v=5" target="_blank" rel="noopener" style="display:inline-block;padding:10px 14px;border-radius:8px;background:#2563eb;color:white;text-decoration:none;font-weight:700;">
    Trainer im Vollbild öffnen
  </a>
</p>

<iframe
  src="https://trainer.ulrich-wiki.com/powershell-schleifen-trainer-01.html?v=5"
  style="width:100%;height:950px;border:0;border-radius:12px;overflow:hidden;"
  loading="lazy">
</iframe>

# Trainer 05 - Schleifenlogik verstehen

<p>
  <a href="https://trainer.ulrich-wiki.com/powershell-trainer-05-schleifenlogik-verstehen.html?v=2" target="_blank" rel="noopener" style="display:inline-block;padding:10px 14px;border-radius:8px;background:#2563eb;color:white;text-decoration:none;font-weight:700;">
    Trainer im Vollbild öffnen
  </a>
</p>

<iframe
  src="https://trainer.ulrich-wiki.com/powershell-trainer-05-schleifenlogik-verstehen.html?v=2"
  style="width:100%;height:1150px;border:0;border-radius:12px;overflow:hidden;"
  loading="lazy">
</iframe>

# Trainer 06 – Do-While und Until

<p>
  <a href="https://trainer.ulrich-wiki.com/powershell-trainer-06-do-while-until.html?v=2" target="_blank" rel="noopener">
    Vollbild öffnen
  </a>
</p>

<iframe
  src="https://trainer.ulrich-wiki.com/powershell-trainer-06-do-while-until.html?v=2"
  style="width:100%; height:1100px; border:0; border-radius:14px;"
  loading="lazy">
</iframe>

# PowerShell – Schleifen kompakt erklärt

**Grundidee**

Eine Schleife wiederholt einen Codeblock, solange eine Bedingung erfüllt ist oder bis eine Abbruchbedingung erreicht wird.

---

**Wichtige Schleifentypen**

| Schleife | Bedeutung | Prüft wann? | Kann 0-mal laufen? |
|---|---|---:|---:|
| while | solange eine Bedingung wahr ist | vorher | ja |
| for | Zählschleife mit Start, Bedingung und Änderung | vorher | ja |
| foreach | läuft durch alle Elemente einer Liste | vorher | ja, wenn Liste leer ist |
| do while | läuft mindestens einmal, dann solange Bedingung wahr ist | danach | nein |
| do until | läuft mindestens einmal, dann bis Bedingung wahr wird | danach | nein |

---

**Abweisende Schleifen**

Abweisende Schleifen prüfen die Bedingung vor dem ersten Durchlauf.

Sie können deshalb 0-mal laufen.

Beispiele:

    while ($x -lt 5) {
    }

    for ($i = 0; $i -lt 3; $i++) {
    }

    foreach ($item in $liste) {
    }

---

**Nicht-abweisende / fußgesteuerte Schleifen**

Diese Schleifen prüfen die Bedingung erst nach dem ersten Durchlauf.

Sie laufen deshalb mindestens 1-mal.

Beispiele:

    do {
    }
    while ($x -lt 5)

    do {
    }
    until ($x -ge 5)

---

**Kopfgesteuert und fußgesteuert**

| Begriff | Bedeutung | Beispiele |
|---|---|---|
| kopfgesteuert | Bedingung wird vor dem Schleifenkörper geprüft | while, for, foreach |
| fußgesteuert | Bedingung wird nach dem Schleifenkörper geprüft | do while, do until |

---

**Schleifenkopf**

Im Schleifenkopf steht die Bedingung oder Steuerung der Schleife.

Beispiel:

    while ($i -lt 5)

---

**Schleifenkörper**

Der Schleifenkörper ist der Code, der wiederholt ausgeführt wird.

Beispiel:

    {
        Write-Host $i
        $i++
    }

---

**Iteration**

Eine Iteration ist ein einzelner Schleifendurchlauf.

Wenn eine Schleife 5-mal läuft, hat sie 5 Iterationen.

---

**Abbruchbedingung**

Die Abbruchbedingung beschreibt, wann die Schleife beendet werden soll.

Beispiel:

    Abbrechen, sobald $i mindestens 5 ist.

Bei do until steht diese Bedingung direkt in der Schleife:

    do {
        $i++
    }
    until ($i -ge 5)

---

**Weiterlaufbedingung**

Die Weiterlaufbedingung beschreibt, solange die Schleife weiterlaufen soll.

Beispiel:

    while ($i -lt 5)

Bedeutung:

    Wiederholen, solange $i kleiner als 5 ist.

---

**while**

while prüft vor jedem Durchlauf.

    $i = 0

    while ($i -lt 3) {
        Write-Host $i
        $i++
    }

Ausgabe:

    0
    1
    2

Warum keine 3?

    3 -lt 3 = falsch

---

**do while**

do while läuft mindestens einmal und prüft danach.

    $x = 10

    do {
        Write-Host $x
    }
    while ($x -lt 5)

Ausgabe:

    10

Die Schleife läuft nur 1-mal, weil danach geprüft wird:

    10 -lt 5 = falsch

---

**do until**

do until läuft mindestens einmal und stoppt, sobald die Bedingung wahr ist.

    $punkte = 0

    do {
        $punkte += 10
    }
    until ($punkte -ge 100)

Bedeutung:

    Wiederholen, bis $punkte mindestens 100 ist.

---

**for**

for ist eine typische Zählschleife.

Aufbau:

    for (Startwert; Bedingung; Veränderung) {
    }

Beispiel:

    for ($i = 0; $i -lt 3; $i++) {
        Write-Host $i
    }

Ausgabe:

    0
    1
    2

Ablauf:

| Durchlauf | $i | Prüfung |
|---:|---:|---|
| 1 | 0 | 0 -lt 3 = wahr |
| 2 | 1 | 1 -lt 3 = wahr |
| 3 | 2 | 2 -lt 3 = wahr |
| Ende | 3 | 3 -lt 3 = falsch |

---

**Leerer Schleifenkörper**

Auch wenn der Schleifenkörper leer ist, läuft die Schleife trotzdem.

    for ($i = 0; $i -lt 3; $i++) {
    }

Diese Schleife läuft 3-mal.

Sie gibt nur nichts aus.

---

**foreach**

foreach wird verwendet, um jedes Element einer Liste zu verarbeiten.

    foreach ($datei in $dateien) {
        Write-Host $datei
    }

Bedeutung:

    Für jede Datei in $dateien wird der Code einmal ausgeführt.

Wenn die Liste leer ist, läuft foreach 0-mal.

---

**Vergleichsoperatoren in PowerShell**

| Operator | Bedeutung |
|---|---|
| -lt | kleiner als |
| -le | kleiner oder gleich |
| -gt | größer als |
| -ge | größer oder gleich |
| -eq | gleich |
| -ne | ungleich |

Beispiele:

    $i -lt 5    # kleiner als 5
    $i -le 5    # kleiner oder gleich 5
    $i -gt 5    # größer als 5
    $i -ge 5    # größer oder gleich 5
    $i -eq 5    # genau 5
    $i -ne 5    # nicht 5

---

**Wichtig: -lt und -le**

    -lt 5 = kleiner als 5

Läuft bei:

    0, 1, 2, 3, 4

Nicht bei:

    5

    -le 5 = kleiner oder gleich 5

Läuft bei:

    0, 1, 2, 3, 4, 5

---

**while vs until**

| Schleife | Bedeutung |
|---|---|
| while | läuft solange die Bedingung wahr ist |
| until | läuft bis die Bedingung wahr wird |

Beispiel mit while:

    do {
        $punkte += 10
    }
    while ($punkte -lt 100)

Bedeutung:

    Wiederholen, solange $punkte kleiner als 100 ist.

Beispiel mit until:

    do {
        $punkte += 10
    }
    until ($punkte -ge 100)

Bedeutung:

    Wiederholen, bis $punkte mindestens 100 ist.

---

**Bei 100 abbrechen**

Wenn bei 100 Schluss sein soll, ist bei do until logisch:

    until ($punkte -ge 100)

Oder bei do while:

    while ($punkte -lt 100)

Nicht passend wäre:

    while ($punkte -le 100)

Denn bei 100 ist diese Bedingung noch wahr und die Schleife läuft nochmal.

---

**Zähler erhöhen**

    $i++

ist dasselbe wie:

    $i += 1

Beide erhöhen den Wert um 1.

---

**Zähler verringern**

    $i--

ist dasselbe wie:

    $i -= 1

Beide verringern den Wert um 1.

---

**Größere Schritte**

    $i += 5

erhöht um 5.

    $i -= 5

verringert um 5.

---

**Initialisierung**

Initialisierung bedeutet: Startwert setzen.

Beispiel:

    $i = 0

---

**Inkrement**

Inkrement bedeutet: Wert erhöhen.

Beispiel:

    $i++

oder:

    $i += 1

---

**Dekrement**

Dekrement bedeutet: Wert verringern.

Beispiel:

    $i--

oder:

    $i -= 1

---

**Endlosschleife**

Eine Endlosschleife endet nicht von selbst.

Beispiel:

    while ($true) {
        Write-Host "läuft"
    }

Oder:

    $x = 1

    do {
        Write-Host $x
    }
    while ($x -lt 5)

Wenn $x nie verändert wird, bleibt die Bedingung immer wahr.

---

**break**

break beendet eine Schleife sofort.

    while ($true) {
        break
    }

---

**continue**

continue überspringt den Rest des aktuellen Durchlaufs und springt direkt zum nächsten Durchlauf.

    for ($i = 1; $i -le 5; $i++) {
        if ($i -eq 3) {
            continue
        }

        Write-Host $i
    }

Ausgabe:

    1
    2
    4
    5

---

**Off-by-one-Fehler**

Ein Off-by-one-Fehler passiert, wenn eine Schleife einmal zu viel oder einmal zu wenig läuft.

Typischer Unterschied:

    $i -lt 5

läuft bis 4.

    $i -le 5

läuft bis 5.

---

**Merksätze**

    while = solange

    until = bis

    for = Zählschleife

    foreach = für jedes Element

    do while = mindestens einmal, dann solange

    do until = mindestens einmal, dann bis

    break = sofort raus

    continue = nächster Durchlauf

    -lt = kleiner als

    -le = kleiner oder gleich

    -gt = größer als

    -ge = größer oder gleich

    -eq = gleich

    -ne = ungleich

# PowerShell Schleifen – Zusatz

**Grundsätzliche Schreibweise**

PowerShell orientiert sich bei Schleifen an C-ähnlichen Sprachen.

Die Schleifenbedingung steht meistens in runden Klammern.

    while ($x -lt 5)

Der Schleifenkörper steht in geschweiften Klammern.

    {
        Write-Host $x
    }

PowerShell-Befehlswörter sind nicht case-sensitive.

Das ist also gleichbedeutend:

    for
    For
    FOR

---

**Abweisende Schleifen**

Abweisende Schleifen prüfen die Schleifenbedingung vor dem ersten Durchlauf.

Wenn die Bedingung direkt am Anfang falsch ist, wird der Schleifenkörper kein einziges Mal ausgeführt.

Beispiele:

    while ($x -lt 5) {
    }

    for ($i = 1; $i -le 10; $i++) {
    }

---

**Nicht-abweisende Schleifen**

Nicht-abweisende Schleifen prüfen die Schleifenbedingung am Ende des Schleifenkörpers.

Der Schleifenkörper wird deshalb mindestens einmal ausgeführt.

Beispiele:

    do {
        Write-Host $x
    }
    while ($x -lt 5)

    do {
        Write-Host $x
    }
    until ($x -ge 5)

---

**for-Schleife**

Die for-Schleife eignet sich, wenn man eine Laufvariable direkt in der Schleifenanweisung initialisieren und inkrementieren möchte.

Aufbau:

    for (Initialisierung; Schleifenbedingung; Inkrementierung) {
        Anweisungen
    }

Beispiel:

    for ($i = 1; $i -le 10; $i++) {
        Write-Host $i
    }

Bedeutung:

    $i wird mit 1 initialisiert.
    Die Schleife läuft, solange $i kleiner oder gleich 10 ist.
    Nach jeder Iteration wird $i inkrementiert.

---

**Laufvariable**

Eine Laufvariable steuert, wie oft eine Schleife läuft.

Beispiel:

    $i

In einer for-Schleife kann die Laufvariable direkt in der Schleifenanweisung gesetzt und verändert werden.

    for ($i = 1; $i -le 10; $i++) {
    }

---

**Initialisieren**

Initialisieren bedeutet: Eine Variable bekommt einen Startwert.

Beispiel:

    $i = 1

---

**Inkrementieren**

Inkrementieren bedeutet: Eine Variable wird erhöht.

Beispiel:

    $i++

Das ist gleichbedeutend mit:

    $i += 1

---

**while-Schleife**

Die while-Schleife ist eine abweisende Schleife.

Sie prüft die Schleifenbedingung vor dem ersten Durchlauf.

Beispiel:

    while ($i -le 10) {
        Write-Host $i
        $i++
    }

Bei while besteht der Ausdruck nur aus einer Bedingung.

Wenn man eine Laufvariable verwenden möchte, muss man sie vorher initialisieren und im Schleifenkörper verändern.

Beispiel:

    $i = 1

    while ($i -le 10) {
        Write-Host $i
        $i++
    }

---

**while mit Eingabe und Zuweisung**

In der Schleifenbedingung einer while-Schleife darf man auch Werte zuweisen oder Eingaben abfragen.

Beispiel:

    while (($inp = Read-Host "Wählen Sie einen Befehl") -ne "Q") {
        Write-Host "Eingabe war $inp"
    }

Bedeutung:

    Read-Host fragt eine Eingabe ab.
    Der Wert wird in $inp gespeichert.
    Solange $inp nicht Q ist, läuft die Schleife weiter.

---

**do-while**

do-while ist eine nicht-abweisende Schleife.

Der Schleifenkörper läuft mindestens einmal.

Beispiel:

    do {
        Write-Host $x
    }
    while ($x -lt 5)

Bedeutung:

    Die Schleife läuft, solange die Bedingung wahr ist.
    Sie bricht ab, wenn die Bedingung nicht mehr erfüllt ist.

---

**do-until**

do-until ist ebenfalls eine nicht-abweisende Schleife.

Der Schleifenkörper läuft mindestens einmal.

Beispiel:

    do {
        Write-Host $x
    }
    until ($x -ge 5)

Bedeutung:

    Die Schleife läuft, bis die Bedingung wahr wird.
    Sie endet, wenn die Schleifenbedingung TRUE wird.

---

**do-while und do-until gegenseitig ersetzen**

do-while und do-until können sich grundsätzlich gegenseitig ersetzen, wenn man die Bedingung negiert.

Beispiel mit do-while:

    do {
        $i++
    }
    while ($i -lt 5)

Gleiche Logik mit do-until:

    do {
        $i++
    }
    until ($i -ge 5)

Merke:

    do-while läuft, solange die Bedingung wahr ist.
    do-until läuft, bis die Bedingung wahr wird.

---

**break**

break dient zur Schleifensteuerung.

break verlässt den aktuellen Block.

In Schleifen beendet break die Iteration und setzt den Programmablauf mit der nächsten Anweisung außerhalb des Schleifenkörpers fort.

Beispiel:

    while ($true) {
        if ($fertig) {
            break
        }
    }

Bedeutung:

    Die Schleife läuft eigentlich dauerhaft.
    Sobald $fertig wahr ist, beendet break die Schleife.

---

**break in switch-Blöcken**

break kann nicht nur in Schleifen verwendet werden, sondern auch innerhalb von switch-Blöcken.

Beispiel:

    switch ($inp) {
        "L" { "Datei wird gelöscht"; break }
        "A" { "Datei wird angezeigt"; break }
        "R" { "Datei erhält Schreibschutz"; break }
        "Q" { "Ende"; break }
        default { "Ungültige Eingabe" }
    }

Bedeutung:

    break verlässt den switch-Block.

---

**break bei verschachtelten Schleifen**

Bei verschachtelten Schleifen verlässt break den aktuellen Schleifenblock.

Beispiel:

    foreach ($a in 1..3) {
        foreach ($b in 1..3) {
            break
        }
    }

Bedeutung:

    break beendet hier die innere Schleife.
    Die äußere Schleife kann weiterlaufen.

---

**break mit Sprungmarke**

PowerShell erlaubt break auch mit einer Sprungmarke.

Eine Sprungmarke beginnt mit einem Doppelpunkt.

Beispiel-Schema:

    :MeineSchleife while ($true) {
        break MeineSchleife
    }

Wichtig:

    break mit Sprungmarke ist möglich.
    Es sollte aber sparsam verwendet werden, weil es Code schwerer verständlich machen kann.

---

**continue**

continue dient ebenfalls zur Schleifensteuerung.

continue bricht die weitere Ausführung des aktuellen Schleifenkörpers ab.

Im Unterschied zu break verlässt continue die Schleife nicht komplett, sondern startet die nächste Iteration.

Beispiel:

    foreach ($zahl in 1..5) {
        if ($zahl -eq 3) {
            continue
        }

        Write-Host $zahl
    }

Ausgabe:

    1
    2
    4
    5

Bedeutung:

    Bei 3 wird der restliche Schleifenkörper übersprungen.
    Danach geht es mit der nächsten Iteration weiter.

---

**Iteration**

Eine Iteration ist ein einzelner Schleifendurchlauf.

Wenn eine Schleife 5-mal läuft, hat sie 5 Iterationen.

---

**Implizite Iteration über Array-Elemente**

PowerShell kann bei Arrays in bestimmten Fällen automatisch über die Elemente iterieren.

Beispiel:

    ($user).Surname

Wenn $user mehrere Objekte enthält, wird die Eigenschaft Surname für jedes Element ausgegeben.

Bedeutung:

    Man braucht nicht immer eine explizite Schleife.
    PowerShell kann Eigenschaften von Array-Elementen teilweise automatisch ausgeben.

---

**foreach-Anweisung**

Die foreach-Anweisung wird verwendet, um über Elemente eines Arrays oder einer Sammlung zu iterieren.

Beispiel:

    $user = Get-ADUser -Filter *

    foreach ($u in $user) {
        $u.Surname
    }

Bedeutung:

    $user enthält mehrere Objekte.
    $u enthält immer das aktuelle Element des Arrays.
    Der Schleifenkörper wird für jedes Element einmal ausgeführt.

---

**ForEach-Object**

ForEach-Object ist ein Cmdlet für die Verarbeitung von Pipeline-Objekten.

Beispiel:

    Get-ADUser -Filter * | ForEach-Object {
        $_.Surname
    }

Bedeutung:

    Die Objekte kommen über die Pipeline.
    ForEach-Object verarbeitet jedes Objekt einzeln.

---

**foreach als Alias für ForEach-Object**

Wichtig: foreach kann zwei Bedeutungen haben.

Als Schleifenanweisung:

    foreach ($u in $user) {
        $u.Surname
    }

Als Alias für ForEach-Object in der Pipeline:

    Get-ADUser -Filter * | foreach {
        $_.Surname
    }

Merke:

    foreach (...) { }     = foreach-Anweisung
    | foreach { }         = Alias für ForEach-Object

---

**% als Alias für ForEach-Object**

% ist ein weiterer Alias für ForEach-Object.

Diese Schreibweisen sind vergleichbar:

    Get-ADUser -Filter * | ForEach-Object {
        $_.Surname
    }

    Get-ADUser -Filter * | foreach {
        $_.Surname
    }

    Get-ADUser -Filter * | % {
        $_.Surname
    }

Merke:

    % = Alias für ForEach-Object

---

**$_**

$_ ist eine automatische Variable.

Bei ForEach-Object steht $_ für das aktuelle Objekt aus der Pipeline.

Beispiel:

    Get-ADUser -Filter * | ForEach-Object {
        $_.Surname
    }

Bedeutung:

    $_ = aktuelles Pipeline-Objekt

---

**foreach-Anweisung vs. ForEach-Object**

Die foreach-Anweisung arbeitet mit einer vorhandenen Sammlung.

    foreach ($u in $user) {
        $u.Surname
    }

ForEach-Object arbeitet typischerweise mit Pipeline-Ausgabe.

    Get-ADUser -Filter * | ForEach-Object {
        $_.Surname
    }

Merke:

    foreach-Anweisung = gut für vorhandene Arrays oder Sammlungen
    ForEach-Object    = gut für Pipeline-Verarbeitung

---

**Performance: foreach-Anweisung und ForEach-Object**

Bei vielen Schleifendurchläufen und komplexeren Berechnungen im Schleifenkörper ist die herkömmliche foreach-Schleife oft schneller.

Beispiel foreach-Anweisung:

    $user = Get-ADUser -Filter *

    foreach ($u in $user) {
        $u.Surname
    }

Beispiel ForEach-Object:

    Get-ADUser -Filter * | ForEach-Object {
        $_.Surname
    }

Merke:

    foreach-Anweisung = oft schneller bei vielen Durchläufen
    ForEach-Object    = oft kürzer und praktisch in der Pipeline

---

**Typische Auswahl der Schleife**

| Zweck | Passende Schleife |
|---|---|
| Laufvariable direkt initialisieren und inkrementieren | for-Schleife |
| Nur eine Bedingung prüfen | while-Schleife |
| Mindestens einmal ausführen und dann Bedingung prüfen | do-while / do-until |
| Elemente eines Arrays verarbeiten | foreach-Anweisung |
| Pipeline-Objekte verarbeiten | ForEach-Object |
| Schleife sofort verlassen | break |
| Aktuelle Iteration überspringen | continue |

---

**Wichtige Merksätze**

    Schleifenbedingung = Bedingung, die den Ablauf der Schleife steuert.

    Schleifenkörper = Anweisungen, die wiederholt ausgeführt werden.

    Abweisende Schleifen können 0-mal laufen.

    Nicht-abweisende Schleifen laufen mindestens 1-mal.

    for-Schleife eignet sich besonders mit Laufvariable.

    while-Schleife eignet sich, wenn nur eine Bedingung geprüft werden soll.

    do-while läuft, solange die Bedingung wahr ist.

    do-until läuft, bis die Bedingung wahr wird.

    break verlässt den aktuellen Block.

    continue startet die nächste Iteration.

    foreach-Anweisung ist nicht dasselbe wie ForEach-Object.

    foreach und % können Aliase für ForEach-Object sein.

    $_ steht für das aktuelle Pipeline-Objekt.

# PowerShell Trainer – Benannte Parameter und Parameter-Dekorator

<div style="background:#111827; border:1px solid #374151; border-radius:14px; padding:20px; margin:18px 0; color:#e5e7eb; font-family:Arial, sans-serif;">

  <h3 style="margin-top:0; color:#f9fafb;">
    PowerShell Trainer – Benannte Parameter und Parameter-Dekorator
  </h3>

  <p style="color:#d1d5db; line-height:1.6;">
    Interaktiver Trainer zu <strong>param()</strong>, <strong>[Parameter()]</strong>,
    <strong>[Alias()]</strong>, <strong>[switch]</strong>, <strong>[ValidateSet()]</strong>,
    Dot-Sourcing und Userprofile-Auswertung.
  </p>

  <p style="margin-top:18px;">
    <a href="https://trainer.ulrich-wiki.com/powershell-parameter-trainer/"
       target="_blank"
       rel="noopener"
       style="display:inline-block; background:#2563eb; color:#ffffff; padding:12px 18px; border-radius:8px; text-decoration:none; font-weight:bold;">
      Trainer im Vollbild öffnen
    </a>
  </p>

  <iframe
    src="https://trainer.ulrich-wiki.com/powershell-parameter-trainer/"
    style="width:100%; height:850px; border:1px solid #374151; border-radius:12px; background:#111827; margin-top:16px;"
    allowfullscreen>
  </iframe>

</div>

# PowerShell Trainer – Fragen und Antworten zu Parametern

<div style="background:#111827; border:1px solid #374151; border-radius:14px; padding:20px; margin:18px 0; color:#e5e7eb; font-family:Arial, sans-serif;">

  <h3 style="margin-top:0; color:#f9fafb;">
    PowerShell Trainer – Fragen und Antworten zu Parametern
  </h3>

  <p style="color:#d1d5db; line-height:1.6;">
    Frage-Antwort-Trainer zu <strong>PowerShell-Parametern</strong>,
    <strong>param()</strong>, <strong>[Parameter()]</strong>,
    <strong>Aliasen</strong>, <strong>Switch-Parametern</strong>,
    <strong>ValidateSet</strong>, Dot-Sourcing und der Funktion
    <strong>check-userprofile</strong>.
  </p>

  <p style="margin-top:18px;">
    <a href="https://trainer.ulrich-wiki.com/powershell-parameter-fragen/"
       target="_blank"
       rel="noopener"
       style="display:inline-block; background:#2563eb; color:#ffffff; padding:12px 18px; border-radius:8px; text-decoration:none; font-weight:bold;">
      Frage-Antwort-Trainer im Vollbild öffnen
    </a>
  </p>

</div>