--- id: P3 titel: Ein Skript schreiben, das man in einem Jahr noch versteht block: programmierung woche: 7 worum: Ein Skript, das nur sein Verfasser bedienen kann, ist eine Abhängigkeit. Ein gutes Skript erklärt sich, prüft seine Eingaben und meldet Fehler, statt sie zu verschweigen. rahmenplan: [A10, A4, A5] lernfeld: LF5 merksatz: Sagen, was es tut. Prüfen, was hineinkommt. Melden, was schiefgeht. Erst mit -WhatIf laufen lassen. karten: - frage: Wozu dient ein param-Block am Anfang eines Skripts? antwort: Er legt fest, welche Eingaben das Skript erwartet, mit Typ und ob sie Pflicht sind. Werte stehen dann nicht fest im Code, und PowerShell fragt fehlende Pflichtangaben selbst ab. - frage: Warum fängt ein try-catch-Block manche Fehler nicht ab, und wie behebt man das? antwort: Viele Cmdlets melden Fehler nur und laufen weiter (nicht abbrechende Fehler). Mit -ErrorAction Stop am Befehl wird daraus ein abbrechender Fehler, den catch auffängt. - frage: Was bewirkt die Ausführungsrichtlinie RemoteSigned? antwort: Selbst geschriebene, lokale Skripte laufen; aus dem Internet heruntergeladene Skripte nur, wenn sie signiert sind. Sie schützt vor versehentlichem Ausführen, ist aber keine Sicherheitsgrenze. --- ## Das Wesentliche - **Ein Kopf mit Hilfe:** Ein Block `<# .SYNOPSIS … .EXAMPLE … #>` ganz oben macht das Skript für `Get-Help .\skript.ps1` lesbar. Darin steht, was es tut, was es braucht und ein Beispielaufruf. - **Eingaben als Parameter**, nicht fest im Code: Pfade, Rechnernamen und Grenzwerte gehören in den `param()`-Block. `[Parameter(Mandatory)]` macht eine Angabe zur Pflicht. - **Namen, die etwas sagen:** `$freierPlatzProzent` statt `$x`. Kommentare erklären das **Warum**, nicht das Was – das Was steht im Code. - **Fehler nicht verschlucken.** `try { … -ErrorAction Stop } catch { … }` fängt Fehler auf und meldet sie verständlich. Ein leerer `catch`-Block ist schlimmer als gar keiner. - **Erst trocken, dann echt.** Mit `[CmdletBinding(SupportsShouldProcess)]` bekommt das eigene Skript `-WhatIf`. Ein Skript, das löscht, ändert oder verschiebt, läuft zuerst so. - **Klein anfangen und testen.** Erst an einem Testrechner, dann an einem echten, dann an allen. Jede Stufe mit Blick auf die Ausgabe. - **Versionieren.** Skripte gehören in ein Git-Repository der IT, nicht auf den Desktop. So sieht man, wer wann was geändert hat, und kommt zur letzten funktionierenden Fassung zurück. - **Ausführungsrichtlinie:** Auf Clients ist meist `RemoteSigned` eingestellt. Sie verhindert versehentliches Ausführen fremder Skripte, ist aber keine Sicherheitsgrenze. ## Übersicht ```powershell <# .SYNOPSIS Löscht Protokolldateien, die älter als eine bestimmte Anzahl Tage sind. .EXAMPLE .\Protokolle-Aufraeumen.ps1 -Pfad D:\Logs -Tage 30 -WhatIf #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)][string]$Pfad, [int]$Tage = 30 ) if (-not (Test-Path $Pfad)) { throw "Den Pfad $Pfad gibt es nicht." } $stichtag = (Get-Date).AddDays(-$Tage) $alt = Get-ChildItem $Pfad -Filter *.log -File | Where-Object LastWriteTime -lt $stichtag foreach ($datei in $alt) { if ($PSCmdlet.ShouldProcess($datei.FullName, 'Löschen')) { try { Remove-Item $datei.FullName -ErrorAction Stop } catch { Write-Warning "Konnte $($datei.Name) nicht löschen: $($_.Exception.Message)" } } } ``` ## Prüfungsfrage **Frage:** Ein Kollege hat ein Skript geschrieben, das auf allen Rechnern temporäre Dateien löscht. Pfad und Rechnerliste stehen fest im Code, Fehler werden nicht behandelt. Nennen Sie vier Verbesserungen und begründen Sie sie. **Antwort:** (1) Pfad und Rechnerliste als Parameter übergeben – das Skript lässt sich dann für andere Fälle nutzen, ohne den Code zu ändern. (2) `-WhatIf` unterstützen und das Skript zuerst trocken laufen lassen – bei einem löschenden Skript lässt sich so vorab prüfen, was betroffen wäre. (3) Fehlerbehandlung mit `try`/`catch` und `-ErrorAction Stop` – damit nicht erreichbare Rechner oder gesperrte Dateien gemeldet und nicht stillschweigend übergangen werden. (4) Einen Hilfeblock mit Beschreibung und Beispiel ergänzen und das Skript im Repository der IT versionieren – so kann es auch jemand anderes betreuen. Ebenfalls richtig: Eingaben prüfen, z. B. mit `Test-Path`, und ein Protokoll der gelöschten Dateien schreiben.