Was
Dieser Artikel bietet einen umfassenden Leitfaden zu Best Practices im PowerShell-Scripting mit Fokus auf Code-Struktur, Ausgabeformatierung, Fehlerbehandlung, Leistungsoptimierung und Sicherheitsmaßnahmen.
Warum
Die Einhaltung von Best Practices im PowerShell-Scripting stellt sicher, dass Skripte lesbar, wartbar, sicher und performant sind. Dadurch werden technische Schulden reduziert, die Zusammenarbeit verbessert und Risiken in Produktionsumgebungen minimiert.
Wie
Tool- und Controller-Design
Entscheiden Sie, ob Sie ein ‚Tool‘ oder einen ‚Controller‘ schreiben
- Tool: Wiederverwendbare Funktionen/Module.
- Controller: Automatisiert eine spezifische Aufgabe, nicht zur Wiederverwendung gedacht.
Machen Sie Ihren Code modular
- Verwenden Sie Funktionen und Skriptmodule für maximale Wiederverwendbarkeit.
Verwenden Sie standardisierte Namenskonventionen
- Verwenden Sie das Verb-Nomen-Format mit genehmigten PowerShell-Verben (
Get-Verb
).
Standardisieren Sie Parameternamen
- Nutzen Sie Namen wie
$ComputerName
anstelle eigener Präfixe.
Tools geben Rohdaten aus
- Tools sollten minimal verarbeitete Daten für Flexibilität ausgeben.
Controller geben formatierte Daten aus
- Controller können benutzerfreundliche Berichte ausgeben.
Beispiel
function Get-DiskInfo {
param ([string]$ComputerName)
Get-WmiObject Win32_LogicalDisk -ComputerName $ComputerName
}
Das Rad nicht neu erfinden
Verwenden Sie integrierte Cmdlets wie Test-Connection
statt eigener Ping-Funktionen.
# Bevorzugt
Test-Connection $ComputerName -Quiet
Schreiben von Parameterblöcken
Immer Hilfe schreiben
Fügen Sie kommentarbasierte Hilfe mit .SYNOPSIS
, .DESCRIPTION
und mindestens einem .EXAMPLE
hinzu.
function Test-Help {
<#
.SYNOPSIS
Zeigt eine korrekte Hilfedokumentation.
.EXAMPLE
Test-Help -MandatoryParameter "Beispiel"
Führt die Test-Help-Funktion mit einem Pflichtparameter aus.
#>
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[Alias("MP")]
[String]$MandatoryParameter
)
}
Verwenden Sie [CmdletBinding()]
Aktiviert gemeinsame Parameter wie -Verbose
, -Debug
, -ErrorAction
.
Unterstützen Sie -WhatIf und -Confirm
Für befehlsverändernde Aktionen SupportsShouldProcess
verwenden.
[CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")]
param ([switch]$Force)
Parameter stark typisieren
Definieren Sie stets Parametertypen für Validierung und Klarheit.
param (
[string]$Name,
[int]$Count
)
[switch] korrekt verwenden
- Standardwert ist
$false
. - Logisch als Boolean verwenden, keine drei Zustände simulieren.
Ausgabeformatierung
Write-Host vermeiden, wenn nicht nötig
Verwenden Sie je nach Bedarf Write-Verbose
, Write-Debug
oder Write-Output
.
Write-Progress für Fortschrittsanzeigen nutzen
Write-Progress -Activity "Verarbeitung" -Status "50% abgeschlossen" -PercentComplete 50
Formatdateien für benutzerdefinierte Objekte verwenden
Definieren Sie .format.ps1xml
-Dateien statt Inline-Formatierung.
Nur einen Typ gleichzeitig ausgeben
Verwenden Sie [OutputType()]
und vermeiden Sie gemischte Objekttypen.
Fehlerbehandlung Best Practices
-ErrorAction Stop mit Cmdlets verwenden
Erzwingen Sie Abbruchfehler für try-catch
.
try {
Get-Item "C:\InvalidPath" -ErrorAction Stop
} catch {
Write-Warning "Element nicht gefunden."
}
$ErrorActionPreference bei Nicht-Cmdlets nutzen
Temporär auf 'Stop'
setzen bei riskanten Operationen.
Flags und $? vermeiden
Stattdessen strukturierte try-catch
-Blöcke nutzen.
$Error[0] oder $_ sofort im catch kopieren
catch {
$errorDetails = $_
Write-Error "Ein Fehler ist aufgetreten: $($errorDetails.Exception.Message)"
}
Leistungsoptimierung
PERF-01 Leistung nur messen, wenn nötig
Verwenden Sie Measure-Command
für Benchmarking.
Measure-Command {
foreach ($item in $data) { Process-Item $item }
}
PERF-02 Balance zwischen Leistung und Lesbarkeit
- Kleine Datenmengen: Lesbarkeit vorziehen.
- Große Datenmengen: Streaming oder .NET-Methoden in Betracht ziehen.
Leserlich, aber weniger performant:
$content = Get-Content -Path file.txt
foreach ($line in $content) {
Do-Something -Input $line
}
Performance-optimiert:
Get-Content -Path file.txt | ForEach-Object {
Do-Something -Input $_
}
Hochperformant mit .NET:
$sr = New-Object System.IO.StreamReader "file.txt"
while ($sr.Peek() -ge 0) {
$line = $sr.ReadLine()
Do-Something -Input $line
}
PERF-03 Sprachfeatures bevorzugen
- Sprachkonstrukte (
foreach
) > .NET-Methoden > Skripte > Cmdlets/Pipeline - Immer messen, bevor optimiert wird.
Sicherheits-Best Practices
Immer PSCredential für Anmeldedaten verwenden
Keine Klartext-Passwörter. [Credential()]
als Parameter nutzen.
param (
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]
$Credential
)
Bei API-Übergaben:
$Insecure.SetPassword($Credential.GetNetworkCredential().Password)
SecureString für sensible Daten nutzen
Sicher abfragen und verschlüsselt speichern.
$Secure = Read-Host -Prompt "Geben Sie sichere Daten ein" -AsSecureString
Sicher in Klartext umwandeln:
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Secure)
$PlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
Anmeldedaten sicher speichern
Export-CliXml
verwenden.
Get-Credential | Export-CliXml -Path C:\secure\cred.xml
$Credential = Import-CliXml -Path C:\secure\cred.xml
Verschlüsselte Zeichenketten speichern
ConvertFrom-SecureString -SecureString $Secure | Out-File -Path "${Env:AppData}\secure.bin"
$Secure = Get-Content -Path "${Env:AppData}\secure.bin" | ConvertTo-SecureString
Fazit
Durch die Befolgung dieser PowerShell-Best-Practices in den Bereichen Design, Dokumentation, Ausgabe, Fehlerbehandlung, Leistung und Sicherheit erstellen Sie robuste, wartbare und effiziente Skripte. Streben Sie stets ein Gleichgewicht zwischen Lesbarkeit, Performance und Sicherheit an, um hochwertige Automatisierungslösungen zu liefern.