3 min read
Skriptabbruch verhindern: PowerShell-Fehler clever behandeln
Da $error eine globale Variable ist, solltest du in Erwägung ziehen, eine eigene Protokollierungsvariable für die...
PowerShell-Erfolgsrezepte – die Profi-Tipps für effektives Scripting
Du willst deine PowerShell-Skripte schneller und flexibler gestalten? Erfahre hier, wie du die Pipeline mit Skriptblöcken und wieder verwendbaren Funktionen optimierst!
Wusstest du, dass du PowerShell-Steuerungsstrukturen Variablen zuweisen kannst, sie aber nicht über die PowerShell-Pipeline übergeben kannst?
Das hier funktioniert problemlos:
# das funktioniert
$result = for ($x=0; $x-lt100; $x+=3)
{
$x
}
$result
Das Weiterleiten der Ergebnisse aus einer Kontrollstruktur an einen anderen Befehl schlägt jedoch fehl:
# das funktioniert nicht (fail)
for ($x=0; $x-lt100; $x+=3)
{
$x
} | Out-GridView
Das liegt daran, dass der PowerShell-Pipeline-Operator (|) eng mit Skriptblöcken ({}) verknüpft ist.
So kannst du eine beliebige Kontrollstruktur als Stream aktivieren und ihr Echtzeitverarbeitung hinzufügen:
# das funktioniert
. {
for ($x=0; $x-lt100; $x+=3)
{
$x
}
} | Out-GridView
Es genügt, die Kontrollstruktur in einen Skriptblock einzuschließen und sie mit dem Operator aufzurufen (es wird kein neuer Variablenbereich angelegt). Mit diesem Wissen kannst du bereits die superschnellen klassischen foreach- oder do-Schleifen innerhalb einer Pipeline verwenden.
Das gesamte PowerShell-Pipeline-Konzept wird durch Skriptblöcke gesteuert. Du kannst ForEach-Object oder Where-Object durch einfache Skriptblöcke ersetzen.
Alle drei Zeilen erzeugen das gleiche Ergebnis:
Get-Service | ForEach-Object { "Working on $($_.DisplayName)..." }
Get-Service | ForEach-Object -Process { "Working on $($_.DisplayName)..." }
Get-Service | . { process { "Working on $($_.DisplayName)..." } }
Auch hier liefern alle drei Zeilen das gleiche Ergebnis:
Get-Service | Where-Object Status -eq Running
Get-Service | Where-Object { $_.Status -like 'Running' }
Get-Service | . { process { if ($_.Status -like 'Running') { $_ } } }
Warum ist das nützlich? Weil du nun ForEach-Object bei Bedarf in einem eigenen Variablenbereich ausführen kannst. Ersetze einfach den . Operator durch &.
Vor allem aber können ForEach-Object und Where-Object leicht in eigenständige Funktionen umgewandelt werden und so wieder verwendbaren Code erstellen. Lass uns das anhand eines Beispiels veranschaulichen.
Hier ist ein "normaler" Pipeline-Ansatz, der alle Dateien im Windows-Ordner auflistet, die innerhalb der letzten 24 Stunden geändert wurden:
$now = Get-Date
$cutoff = $now.AddHours(-24)
Get-ChildItem -Path c:\Windows -File | Where-Object { $_.LastWriteTime -gt $cutoff }
In diesem speziellen Skript funktioniert es gut, aber das Filtern von Dateien nach "Alter" ist etwas, das in vielen Skripten nützlich sein könnte. Du willst vielleicht nicht immer von vorne anfangen. Sehen wir uns an, wie das neue Wissen über Skriptblöcke helfen kann, Ad-hoc-Befehle wie ForEach-Object und Where-Objekt in neue und nützliche spezialisierte Befehle zu verwandeln.
Übersetzt in Skriptblöcke sieht der bisherige Code wie folgt aus:
$now = Get-Date
$cutoff = $now.AddHours(-24)
Get-ChildItem -Path c:\Windows -File | & { process { if ($_.LastWriteTime -gt $cutoff) { $_ } } }
Jeder Skriptblock kann leicht in eine Funktion umgewandelt werden, indem man das Schlüsselwort "function" verwendet und ihm einen Namen gibt:
function Filter-NewFile
{ process { if ($_.LastWriteTime -gt $cutoff) { $_ } } }
$now = Get-Date
$cutoff = $now.AddHours(-24)
Get-ChildItem -Path c:\Windows -File | Filter-NewFile
An dieser Stelle ist der Code viel strukturierter und leichter zu lesen. Außerdem läuft die Funktion jetzt etwa 10 Mal schneller als ForEach-Object oder Where-Object.
Um die Funktion wirklich wieder verwendbar zu machen, müsste man nur die Hilfsvariablen, die sie benötigt, internalisieren. Mit nur wenigen Änderungen ist aus dem ursprünglichen Code ein vielseitiger, wieder verwendbarer Befehl geworden, der in vielen zukünftigen Projekten nützlich sein kann:
function Filter-NewFile
{
param
(
[int]$Hours
)
begin
{
$now = Get-Date
$cutoff = $now.AddHours(-$Hours)
}
process
{
if ($_.LastWriteTime -gt $cutoff)
{ $_ }
}
}
Get-ChildItem -Path c:\Windows -File | Filter-NewFile -Hours 480
Entfessele das volle Potenzial von PowerShell mit unserem praktischen Poster. Egal, ob frischer Einsteiger oder erfahrener Profi, dieser Spickzettel ist so konzipiert, dass du schnell die wichtigsten und am häufigsten verwendeten Cmdlets findest.
Entfessele das volle Potenzial von PowerShell mit unserem praktischen Poster. Egal, ob frischer Einsteiger oder erfahrener Profi, dieser Spickzettel ist so konzipiert, dass du schnell die wichtigsten und am häufigsten verwendeten Cmdlets findest.
Das Poster ist zum Download und in Papierform erhältlich.
Okt 17, 2024 by Aleksandar Nikolić und Dr. Tobias Weltner
Da $error eine globale Variable ist, solltest du in Erwägung ziehen, eine eigene Protokollierungsvariable für die...
Okt 24, 2024 by Aleksandar Nikolić und Dr. Tobias Weltner
Hier kommt die nächste Strategie zur Fehlerbehandlung, nachdem wir zuvor die Echtzeit und verzögerte Fehlerbehandlung...
Okt 10, 2024 by Aleksandar Nikolić und Dr. Tobias Weltner
Du bist mit try...catch vertraut? Exceptions kannst du mit Trap-Anweisungen behandeln. Kurz und knackig kommt hier der...
Tobias Weltner und Aleksandar Nikolić haben gemeinsam die Blogpost-Reihe „Tobias&Aleksandars PowerShell-Tipps“ verfasst. Deshalb möchten wir euch beide hier vorstellen:
----------------------------
Aleksandar Nikolić ist ein Microsoft Azure MVP und Mitbegründer von PowerShellMagazine.com, der ultimativen Online-Ressource für PowerShell-Enthusiasten. Mit über 18 Jahren Erfahrung in der Systemadministration ist er ein angesehener Trainer und Redner, der rund um den Globus reist, um sein Wissen und seine Fähigkeiten über Azure, Entra und PowerShell weiterzugeben. Er hat auf IT-Veranstaltungen wie Microsoft Ignite, ESPC, NIC, CloudBrew, NTK und der PowerShell Conference Europe gesprochen.
----------------------------
Tobias ist ein langjähriger Microsoft MVP und war von Anfang an an der Entwicklung von PowerShell beteiligt. Er hat die PowerShell IDE „ISESteroids“ erfunden, zahlreiche Bücher über PowerShell für Microsoft Press und O'Reilly geschrieben, die PowerShell Conference EU (psconf.eu) gegründet und trägt derzeit als Mitglied der „Microsoft Cmdlet Working Group“ zur Weiterentwicklung der PowerShell bei. Tobias gibt sein Wissen als Berater in Projekten und als Trainer in Inhouse-Schulungen für zahlreiche Unternehmen und Agenturen in ganz Europa weiter.