PowerShell 7 hat sich längst von seinem Image als reines „Skript‑Werkzeug“ emanzipiert. Dank Open Source, dem Sprung auf .NET Core und inzwischen .NET 9 (seit Version 7.5) bekommst du heute eine plattformübergreifende Automatisierungs‑, Scripting‑ und sogar Entwicklungsumgebung in einem Paket. Für uns Systemintegratoren eröffnet das zwei hochspannende Spielwiesen:
- Wiederverwendbare Module bauen, die im Team sauber versioniert und zuverlässig verteilt werden können.
- Rich‑Desktop‑Tools mit WPF‑Front‑End erstellen, ohne Visual Studio C# bemühen zu müssen.
Der Artikel führt dich durch alle wesentlichen Neuerungen, erläutert Best Practices aus Kundenprojekten und zeigt Stolperfallen, damit du deine nächsten PowerShell‑Projekte robust, wartbar und zukunftssicher aufsetzt.
1 – Was ist neu in PowerShell
7.5 GA – Stabilität, Feinschliff, Performance
- .NET 9: Aktuelles Fundament + 18 Monate Support – PowerShell 7.5 setzt auf .NET 9.0.1 und erhält 18 Monate Wartung; 7.4 bleibt als LTS bis Nov 2026
- Neue Cmdlets –
ConvertTo‑CliXml/ConvertFrom‑CliXmlerlauben dir, Objekte als reinen XML‑String zu serialisieren oder daraus wiederherzustellen – praktisch für schnelle IPC‑Szenarien. - PSResourceGet 1.1.0 ersetzt PowerShellGet als Standard und unterstützt u. a. authentifizierte Repos und Container‑Feeds.
- PSReadLine 2.3.6 bringt bessere Predictive‑IntelliSense und stabilere History‑Suche.
- Fehler mit Lösungsvorschlag – das Concise‑Error‑View zeigt jetzt
RecommendedAction, sodass dir ein möglicher Fix sofort eingeblendet wird. - Tab‑Completion 2.0 – Tilde‑Expansion (
~) klappt jetzt auch unter Windows, Parameter wie‑Verboder‑Scopeliefern Kontext‑Vorschläge,New‑ItemPropertykennt seine‑PropertyType. - Performance‑Kick: Das berüchtigte
+=auf Arrays wurde massiv optimiert und schlägt in 7.5 sogarList<T>.Add()in vielen Szenarien.
Dazu kommen Dutzende Detailverbesserungen:
– Remove‑Item zeigt Fortschrittsbalken, Start‑Process ‑PassThru liefert den ExitCode korrekt, Test‑Json ignoriert optional Kommentare, ConvertFrom‑Json bekommt ‑DateKind, Get‑Process ‑IncludeUserName funktioniert ohne Admin‑Token u. v. m.
7.6‑Preview – Blick in die Zukunft
- ThreadJob wird Microsoft.PowerShell.ThreadJob – neues Paket, altes Alias bleibt als Proxy für rückwärtskompatible Skripte.
- Multi‑Path‑Join‑Path –
‑ChildPathakzeptiert Arrays; aufpassen bei bestehenden Skripten. - Weitere Tab‑Completion‑Verbesserungen, Bugfixes und kleinere Breaking‑Changes werden laufend nachgereicht; produktiv bleibt 7.5 vorerst die Empfehlung.
2 – Warum Module?
Ein loses Sammelsurium einzelner .ps1-Dateien skaliert nur, solange Sie allein daran arbeiten – größere Teams verlieren hier rasant den Überblick. Ein Modul (PSM1 + PSD1) kapselt Funktionen, Variablen, Klassen und Abhängigkeiten in einem wohldefinierten Paket. Dadurch entsteht eine klare Contract‑Boundary: Außenstehenden ist sofort ersichtlich, welche Public‑Cmdlets verfügbar sind und welche privaten Helfer verborgen bleiben. Microsoft fasst diese Rolle eines Moduls als „kleinste logisch wiederverwendbare Einheit“ zusammen.
Manifest & SemVer – denen man vertraut
Im Module‑Manifest (MyTools.psd1) pflegen Sie nicht nur Autor, Copyright und Minimum‑PSEdition, sondern vor allem eine semantische Versionsnummer (ModuleVersion = '1.4.2'). Befolgen Sie strikt [SemVer 2.0.0]; ein Major‑Sprung signalisiert Breaking Changes, Minor steht für rückwärtskompatible Features und Patch fixiert Bugs. CI‑Pipelines können so exakt prüfen, ob ein Upgrade zulässig ist, ohne produktive Skripte zu zerlegen.
Projektstruktur & Namenskonventionen
- Ordnerlayout:
Public\für exportierte Cmdlets,Private\für Helper,Classes\für‑DSC‑oder‑OOP‑Code; Autoload erfolgt viaExport‑ModuleMember. - Cmdlet‑Namen folgen dem Verb‑Noun‑Schema der offiziellen Verb‑Liste; prüfen Sie es per
Get‑Verb. - Alias‑Falle: Aliase nur für Tippfaulheit im Terminal; im Modulcode selbst unbedingt umgehen. Diese Konventionen unterstützt PSScriptAnalyzer mit Regeln wie
PSUseApprovedVerbs. Microsoft LearnMicrosoft Learn
Autoloading & Dependency‑Management
Sobald ein Skript Get‑MyDisk aufruft, das nicht im aktuellen Scope existiert, lädt PowerShell das entsprechende Modul automatisch aus $env:PSModulePath. Im Manifest deklarieren Sie RequiredModules – einschließlich Minimalversion – und ExternalModuleDependencies für optionale Plug‑ins. Beim Packen prüft PSResourceGet diese Liste; fehlende Pakete werden nachinstalliert oder ein Publish‑Vorgang schlägt ab. Microsoft LearnGitHub
Distribution: Public, Private, Hybrid
- Öffentlich:
Publish‑PSResource -Repository PSGallery -ApiKey $keyentlädt Ihr Paket in die PowerShell Gallery. Vergessen Sie nicht, Tags (Cloud,M365,WPF) und kompatible Plattformen zu setzen. - Intern: Ein NuGet‑Feed (Artifactory, ProGet, Azure DevOps Artifacts) oder gar ein simpleres FileShare‑Repository wird per
Register‑PSResourceRepositoryeingebunden. Rollenbasierte Authentifizierung hält proprietären Code unter Verschluss. - Hybrid: Mehrere Repos lassen sich priorisieren (
–Priority); damit beziehen Sie Community‑Pakete aus der Gallery, während Unternehmens‑Module nur intern gesucht werden.
Security: Signieren, Scopes & ExecutionPolicy
Setzen Sie die Firmen‑CA als Stammzertifikat und signieren Sie Releases via Set‑AuthenticodeSignature. In Kombination mit Set‑ExecutionPolicy -Scope CurrentUser -ExecutionPolicy AllSigned verhindern Sie, dass ungeprüfte Skripte laufen.
Die Gallery akzeptiert seit 2024 ebenfalls Signaturen und verweigert nicht signierte Updates für Module mit PowerShellGetPrerelease‑Flag.
Qualität | PSScriptAnalyzer & Pester
- Static Code Analysis:
Invoke‑PSScriptAnalyzerintegriert sich in GitHub Actions oder Azure Pipelines; Regeln wiePSAvoidUsingWriteHostreduzieren Wartungsaufwand. - Tests: Legen Sie unter
tests/Pester‑Dateien ab. EinTest‑Driven‑Moduleliefert bei jedem Commit ein Deployment‑artefakt erst, wenn alle Tests grün sind.
So wird aus „funktioniert auf meinem Laptop“ ein reproduzierbares Release.
CI/CD‑Pipelines & Release‑Automatisierung
Ein typischer GitHub‑Workflow:
- Checkout + Cache Abhängigkeiten
pwsh -c Invoke‑Pesterpwsh -c Publish‑PSResource -Path . -Repository Internal(nur auf main‑Branch)dotnet publishfür Self‑Contained Tools
Damit sind Rollbacks dank Versioning nur einen Befehl entfernt.
Kompatibilitätslayer für Windows‑PowerShell‑Module
Sollten Sie auf das alte ActiveDirectory‑ oder AzureAD‑Modul angewiesen sein, genügt oft:
Import‑Module AzureAD -UseWindowsPowerShellPowerShell 7 öffnet im Hintergrund eine 5.1‑Session (WinPSCompatSession) und proxy‑t die Cmdlets. Beachten Sie jedoch den Overhead – kritische Jobs sollten schnellstmöglich auf native 7.x‑Module migriert werden.
3 – Best‑Practices für Modulentwicklung
Gerüst – schneller zum sauberen Modul
Der erste Schritt ist und bleibt New‑ModuleManifest, das Manifest legt Name, Version und Root‑Module fest. Anschließend empfiehlt sich eine dreigeteilte Ordnerstruktur:
MyTools\
├─ Public\ # exportierte Cmdlets
├─ Private\ # Helper‑Funktionen
└─ Classes\ # DSC‑ oder OOP‑Klassen
Jede Funktion wohnt in einer eigenen .ps1-Datei; das hält Git‑Diffs klein und erlaubt selektives Laden. Wer nicht bei Null anfangen will, greift zu Catesta (Invoke‑ModuleScaffold -ModuleName MyTools) oder Plaster:
powershellKopierenBearbeitenInvoke‑Plaster -TemplatePath (Get‑PlasterTemplate -IncludeInstalledModules |
Where‑Object Title -eq 'Module').TemplatePath -Destination ./MyTools
Beide Werkzeuge legen Tests, CI‑Pipelines und README gleich mit an und ersparen eine Stunde manueller Klickarbeit. GitHubGitHub
Code‑Qualität – Pester & GitHub Actions
Jede Public‑Funktion bekommt eine gleichnamige *.Tests.ps1. Mit Pester 5 setzen Sie auf ein modulares, objekthaftes Test‑Framework; die Tests werden versioniert wie Quellcode. Im CI empfiehlt sich ein minimaler Workflow:
name: Run unit tests
uses: PSModule/Invoke-Pester@v2
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: pester-results
path: TestResults.xml
Damit brechen Pull‑Requests bei fehlgeschlagenen Tests automatisch ab, und ein Artefakt dokumentiert das Ergebnis dauerhaft.
Signaturen & Security – Single‑File‑Builds
Für den Release‑Branch empfiehlt sich ein „Flattening“: Die einzelnen Quelldateien werden zu einem kompakten MyTools.psm1 zusammengeführt (z. B. via Build‑Module.ps1). Dieses File signieren Sie anschließend:
$cert = Get‑ChildItem Cert:\CurrentUser\My –CodeSigningCert
Set‑AuthenticodeSignature -FilePath .\dist\MyTools.psm1 -Certificate $cert
Ein signiertes Einzel‑File lädt schneller, erfüllt Audit‑Anforderungen und harmoniert mit einer AllSigned-ExecutionPolicy. Microsoft Learn
Dokumentation – Help as Code
Kommentar‑basierte Help (<# .SYNOPSIS … #>) gehört direkt über jede Funktion. Für externe Hilfe setzen Sie PlatyPS ein:
New‑MarkdownHelp -ModulePath .\MyTools -OutputFolder .\docs
Update‑MarkdownHelp -Path .\docs -RefreshModulePageDadurch entstehen Markdown‑Dateien, die wie jede andere Quelle im Repo leben; Git‑Diffs zeigen sofort, wenn ein Parameter ohne Doc‑Update geändert wurde. Später kann ConvertTo‑Maml sogar eine Updateable Help-ZIP erzeugen. Microsoft LearnGitHub
4 – WPF GUI – warum nicht einfach WinForms?
WinForms ist für schnelle Admin‑Tools zwar nach wie vor der “Quick‑and‑Dirty‑Champion”, doch die Technik rendert jedes Steuerelement absolut – DPI‑Skalierung, High‑Contrast‑Themes oder Rundungen von Windows 11 werden nur unvollständig übernommen. Das Ergebnis wirkt deshalb schnell wie eine App aus der XP‑Ära und bricht auf 4‑K‑Displays gern auseinander.
WPF setzt auf XAML als deklarative Beschreibungssprache und trennt damit Layout klar vom Code‑Behind (PowerShell oder C#). Dank Data Binding genügt eine einzige Property‑Zuweisung, um komplette Tabellen oder TreeViews automatisch zu aktualisieren; Styles & Templates erlauben ein Theme‑fähiges Design ohne zusätzliche CSS‑Frameworks. Gerade größere Oberflächen werden so überschaubar, weil sich UI‑Elemente logisch gruppieren und wiederverwenden lassen.
Offiziell läuft WPF unter .NET Core/.NET 9 ausschließlich auf Windows – die Runtime enthält weiterhin Win32‑Abhängigkeiten. Wer jedoch wirklich plattformübergreifend entwickeln möchte, greift entweder zu Avalonia (ein WPF‑ähnliches XAML‑Framework für Windows, macOS und Linux) oder bindet PowerShell‑Skripte über PSAvalonia direkt ein. Alternativ bringt .NET MAUI eine XAML‑Syntax mit, die per Community‑Toolkit auf Desktop‑ und Mobil‑OS verteilt werden kann – allerdings weichen Controls und Namensräume etwas von klassischem WPF ab.
5 – Werkzeuge zum Entwurf
- Visual Studio 2022 Community mit dem WPF‑Designer ist meiner Meinung nach noch immer die komfortabelste Option.
- VS Code + PowerShell Pro Tools: bietet einen leichten XAML‑Designer und kompiliert Skripts bei Bedarf zu einer EXE.
- PoshGUI oder Web‑Designer für schnelle Mock‑ups – für kleine Tools völlig ausreichend. Reddit
6 – Praxisbeispiel: Modul + WPF‑Frontend
Angenommen, wir wollen eine GUI zum schnellen Prüfen freier Festplattenkontingente auf File‑Servern bauen:
# DiskTools.psm1 (Public/Disk.ps1)
function Get-DiskQuota {
[CmdletBinding()]
param(
[Parameter(Mandatory)][string]$ComputerName
)
Get-CimInstance -ComputerName $ComputerName -ClassName Win32_LogicalDisk |
Select-Object DeviceID, @{N='FreeGB';E={[math]::Round($_.FreeSpace/1GB,1)}}
}
Export-ModuleMember -Function Get-DiskQuota
# MainWindow.xaml (Auszug)
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Disk Quota Checker" Height="240" Width="460">
<Grid Margin="10">
<TextBox x:Name="txtServer" Width="240" Height="24"/>
<Button Content="Prüfen" Width="80" Height="24" Margin="260,0,0,0"
Click="Check_Click"/>
<DataGrid x:Name="dgResult" Margin="0,40,0,0"/>
</Grid>
</Window>
# Launch.ps1
Import-Module .\DiskTools.psd1
Add-Type -AssemblyName PresentationFramework
[xml]$xaml = Get-Content .\MainWindow.xaml
$reader = New-Object System.Xml.XmlNodeReader $xaml
$window = [Windows.Markup.XamlReader]::Load($reader)
$window.FindName('Check_Click').Add_Click({
$srv = $window.FindName('txtServer').Text
$data = Get-DiskQuota -ComputerName $srv
$window.FindName('dgResult').ItemsSource = $data
})
$window.ShowDialog()Das UI bleibt schlank, die Business‑Logik steckt sauber gekapselt im Modul. Durch Data Binding muss keine Schleife manuell die Grid‑Zeilen füllen; das WPF‑Framework aktualisiert die Ansicht automatisch.
7 – MVVM light für PowerShell
Für größere Projekte lohnt sich ein leichtes MVVM‑Pattern: View‑Model‑Klassen in Powershell definieren, INotifyPropertyChanged via [ComponentModel.INotifyPropertyChanged()]‑Attribut hinzufügen und mit Lazy‑Loading die Modul‑Funktionen asynchron aufrufen. Das Beispiel‑Template auf Reddit zeigt, wie man ProgressBars und Status‑Leisten ohne Blockierung der UI kapselt. Reddit
8 – Deployment & Updates
- Self‑Contained: Mit
dotnet publish -p:PublishSingleFile=truelässt sich PowerShell 7 samt abhängigen DLLs in ein Verzeichnis legen – ideal für Clients ohne Admin‑Rechte. - MSIX / WinGet: Ein signiertes MSIX‑Paket mit
pwsh.exe, Modul und XAML kann per Intune ausgerollt werden und aktualisiert sich via PSResourceGet automatisch. - Cross‑Platform: Auf macOS oder Linux einfach das Modul publizieren – das GUI‑Teil kann dort über Avalonia‑Bindings laufen oder mittels Device‑Fallback deaktiviert werden.
9 – Tuning & Troubleshooting
- Performance: Lange Tasks nie im GUI‑Thread ausführen;
Start‑Job,ThreadJoboder[System.Threading.Tasks.Task]+asyncawaitaus dem Template nutzen. - Kompatibilität: Wenn Legacy‑Cmdlets (z. B.
Get‑ADUser) fehlen, den Windows‑Kompatibilitätsmodus (Import‑Module -UseWindowsPowerShell) einsetzen. - Security: Mit
Set‑AuthenticodeSignatureModule signieren und ExecutionPolicy für Userscope auf AllSigned setzen. In gemischten Umgebungen hilft ein KeyVault‑gesicherter Stamm‑Cert.
Fazit
Mit PowerShell 7.5, sauber strukturierten Modulen und einem schlanken WPF‑Frontend baust du heute Tools, die früher klares C#‑Terrain waren. Befolgst du die hier skizzierten Best Practices – klare Ordnerstrukturen, automatisierte Tests, SemVer‑Versionierung, asynchrone Aufrufe und moderne Packaging‑Wege – erhältst du wartbare, performante Lösungen, die im Admin‑Alltag ebenso glänzen wie beim End‑User. Jetzt heißt es: Modul‑Template klonen, XAML entwerfen und loslegen. Viel Spaß beim Coden!

