- 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
Funktionen und Module
Sobald deine Skripte mehr als 50 Zeilen haben, willst du sie strukturieren. Funktionen sind dafür das wichtigste Werkzeug: wiederverwendbare Code-Blöcke mit Namen. Und sobald deine Funktionen woanders auch nützlich sind, packst du sie in ein Modul – das ist der nächste Schritt zur Wiederverwendbarkeit.
PowerShell-Funktionen sind besonders mächtig: sie können wie Cmdlets aussehen und sich verhalten – mit Parameter-Validierung, Pipeline-Unterstützung, Help-Kommentaren. Du kannst praktisch deine eigenen Cmdlets schreiben. Das ist ein riesiger Unterschied zu Bash-Funktionen, die viel einfacher gestrickt sind.
1) Die einfache Funktion
Im Kern ist eine Funktion sehr simpel – nur ein benannter Codeblock:
Beachte den Namen Sag-Hallo – mit Bindestrich nach dem Verb-Substantiv-Schema aus L2. Das ist Konvention: eigene Funktionen sollen ausschauen wie Cmdlets. Erlaubte Verben checken mit Get-Verb. Auch ohne Bindestrich erlaubt (function meine_funktion), aber unschön.
2) Parameter: positionsbasiert und benannt
Funktionen werden interessant wenn sie Argumente bekommen. Der einfachste Weg: $args für alle Argumente, oder benannte Parameter mit der param()-Notation:
Die param()-Variante ist die professionelle. Sie macht deine Funktion zu einem echten Cmdlet-ähnlichen Werkzeug: Tab-Completion zeigt die Parameter, Get-Help kann die Doku rendern, Validierung funktioniert. Für ernste Skripte: immer param().
3) Der param-Block im Detail
Der wahre Power des param()-Blocks zeigt sich mit Typen und Validierungs-Attributen. Klick die Zeilen durch:
if in deiner Funktion schreiben um zu prüfen ob das Alter zwischen 18 und 99 liegt. Das spart Code und macht Bugs unmöglich.4) Validierungs-Attribute: Übersicht
Die wichtigsten Validatoren die du regelmäßig brauchen wirst:
| Attribut | Was es prüft |
|---|---|
[Parameter(Mandatory)] | Parameter ist Pflicht |
[ValidateNotNull()] | Darf nicht $null sein |
[ValidateNotNullOrEmpty()] | Auch kein leerer String |
[ValidateLength(3,20)] | String-Länge zwischen 3 und 20 |
[ValidateRange(0,100)] | Numerisch zwischen 0 und 100 |
[ValidateSet("a","b","c")] | Nur diese Werte erlaubt (Tab-Completion!) |
[ValidatePattern("^\d{4}$")] | String muss Regex matchen |
[ValidateScript({...})] | Beliebige ScriptBlock-Prüfung |
[ValidateCount(1,10)] | Array muss 1 bis 10 Elemente haben |
Diese Validatoren laufen bevor deine Funktion auch nur einen Befehl ausführt. Falsche Eingaben werden mit klaren Fehlermeldungen abgelehnt. Das ist defensive Programmierung auf höchstem Niveau – ohne dass du dafür Validierungs-Code schreiben musst.
5) Pipeline-Funktionen: begin/process/end
Eine Funktion die Pipeline-Input verarbeiten will, braucht die drei Blöcke begin, process und end. Das ist wie eine Fabrik mit drei Stationen:
Ein praktisches Beispiel – eine Funktion die Zähler über die Pipeline laufende Elemente führt:
6) Rückgabewerte
PowerShell-Funktionen sind hier sehr eigen – alles was in der Funktion auf stdout landet, wird zur Rückgabe. Das ist anders als in den meisten Sprachen wo nur return X zurückgibt:
Diese „implizite Rückgabe" ist eines der größten PowerShell-Gotchas. Wenn du nicht aufpasst, gibt deine Funktion plötzlich Zwischenergebnisse mit zurück. Lösungen:
- Zwischenergebnisse in Variablen speichern:
$x = Get-Processstatt nurGet-Process - Output umleiten:
Get-Process | Out-Nullverwirft die Ausgabe - Cast zu void:
[void](Get-Process)oder$null = Get-Process - Write-Host für Anzeige: das geht NICHT in die Pipeline (anders als
Write-Output)
7) Help-Kommentare: Get-Help für eigene Funktionen
Mit speziellen Kommentaren kannst du Get-Help auch für deine eigene Funktion zum Laufen bringen:
Diese Comment-Based-Help ist das Mindeste für produktive Skripte. Wer deine Funktion benutzt, ruft Get-Help auf und kriegt sofort eine Anleitung – wie bei jedem eingebauten Cmdlet aus L2.
8) [CmdletBinding] – aus Funktion mach Cmdlet
Mit dem Attribut [CmdletBinding()] wird deine Funktion zu einem „Advanced Function" – fast nicht von einem echten Cmdlet zu unterscheiden:
SupportsShouldProcess ist Gold wert: deine Funktion bekommt automatisch -WhatIf und -Confirm wie bei „echten" Cmdlets. Bei zerstörerischen Operationen ist das Pflicht. Mehr dazu in L2 Common Parameters.
9) Module – Code zum Wiederverwenden
Wenn du Funktionen in mehreren Skripten nutzen willst, packst du sie in ein Modul. Ein Modul ist eine .psm1-Datei (technisch das Gleiche wie .ps1 – die Endung markiert sie als Modul):
Nutzen in einem Skript:
Module ablegen kannst du an beliebigen Pfaden. Aber damit Import-Module MeineHelfer ohne Pfad funktioniert, muss das Modul in einem der Standard-Modulpfade liegen – meist ~\Documents\PowerShell\Modules\. Alle Pfade ansehen mit $env:PSModulePath -split ";".
10) Module aus der PowerShell Gallery
Microsoft betreibt die PowerShell Gallery – ein zentrales Repository für Module, ähnlich wie PyPI für Python oder NPM für Node.js. Mit Install-Module ziehst du fertige Module direkt aus dem Internet:
Install-Module Az. Alle Azure-Ressourcen über PowerShell.Install-Module -Name Az -Scope CurrentUser – ohne Admin-Rechte. Suchen mit Find-Module *backup*. Updaten mit Update-Module Az. Vor erstem Install fragt PowerShell ob du die PowerShell Gallery als „trusted" markieren willst – ja sagen für gängige Module. Vorsicht bei wenig-bekannten Modulen – wie bei NPM und PyPI gibt es auch hier theoretisch Risiken durch Schad-Module.11) Best Practices für Funktionen
Die Punkte die deine PowerShell-Funktionen professionell machen:
- Verb-Substantiv-Namen nach Schema, mit Bindestrich.
Get-Verbzeigt erlaubte Verben. - param-Block mit Typen und Validierungs-Attributen – nicht
$args. - Mandatory-Parameter explizit markieren.
- [CmdletBinding()] für Advanced Functions.
- begin/process/end bei Pipeline-Funktionen, IMMER process verwenden.
- SupportsShouldProcess +
$PSCmdlet.ShouldProcess(...)bei zerstörerischen Operationen. - Comment-Based-Help für jede öffentliche Funktion.
- Eine Funktion = eine Aufgabe. Wenn sie 100+ Zeilen wird: zerlegen.
- Keine Write-Host für Daten. Daten gehören in die Pipeline (
Write-Outputoder implizit). Write-Host nur für Info/Warnungen an den User. - Mit PSScriptAnalyzer prüfen bevor du das Skript live nimmst – findet typische Probleme.
Mehr zu sauberer PowerShell-Programmierung mit Tests und Linting in den fortgeschrittenen Secure-Coding-Themen in K11 und CI/CD-Pipelines in K54.
Zusammenfassung
Funktion: function Verb-Substantiv { ... } nach Cmdlet-Schema. Mit param()-Block für benannte Parameter, Typen und Validierung. Mandatory, ValidateSet, ValidateRange u.a. machen deine Funktion robust. Pipeline-Funktionen brauchen begin/process/end – process für jedes Element. [CmdletBinding()] macht aus Funktion „Advanced Function". Mit SupportsShouldProcess und $PSCmdlet.ShouldProcess() bekommt sie -WhatIf und -Confirm. Rückgabe: implizit alles was auf stdout geht – $null = Cmd zum Verwerfen. Comment-Based-Help für Get-Help. Module (.psm1) bündeln Funktionen für Wiederverwendung. Import-Module lädt sie, Install-Module holt aus PowerShell Gallery (Az, ExchangeOnline, Pester, ActiveDirectory, ...). Best Practices: Verb-Substantiv-Namen, param mit Validierung, eine Funktion = eine Aufgabe, kein Write-Host für Daten, mit PSScriptAnalyzer linten.
