Som namnet antyder är PowerShell mycket kraftfullare än den vanliga kommandotolken i Windows. Med den kraften följer en större möjlighet till förvirrande fel. Om ditt skript plötsligt misslyckas kanske du inte vet var du ska börja leta efter vad som gick fel. Det är här som PowerShells felhantering kommer väl till pass.
Om du är bekant med andra språk känner du förmodligen till grunderna för felhantering, men det finns några aspekter som är specifika för PowerShell som du behöver känna till. Det finns fyra delar av felhanteringen i PowerShell: parametern Error Action (felåtgärd), Try/Catch-block, parametern Error Variable (felvariabel) och loggning.
PowerShell-felhantering på ett enkelt sätt
Det första steget i hanteringen av PowerShell-fel är att hantera något som stoppar skriptet. Om felet inte påverkar resten av ditt skript kan det vara bäst att bara säga åt PowerShell att ignorera fel och gå vidare.
Å andra sidan är det inte alltid tydligt när en viss cmdlet kastar ett avslutande fel. Vissa cmdlets returnerar ett fel men stoppar inte skriptet. Detta kan leda till att du får vänta på att ditt skript ska avslutas medan det matar ut nonsens.
Det är här parametern -ErrorAction kommer in i bilden. Du använder den för att tvinga en cmdlet att hantera felet på det sätt du vill. Om du ändrar ett befintligt skript lägger du till den i slutet av cmdlet-linjen.
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Stop
Om du använder cmdlet Get-ChildItem på egen hand gör det här felet naturligtvis inte mycket för dig. Men om du vill göra något med uppgifterna är det bra att stoppa skriptet så att du vet att sökningen misslyckades och varför. Om du gör flera sökningar kan du också ändra parametern från Stop till SilentlyContinue, så att skriptet fortsätter om en sökning misslyckas. Om du vill se vad felet är kan du istället använda Continue som parameter.
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction SilentlyContinue
Om du hellre vill ha möjlighet att styra vad som händer varje gång skriptet körs kan du ändra parametern till Inquire. När din cmdlet stöter på ett problem ger den alternativ: Om du väljer att använda din cmdlet: Ja, Ja för alla, Stoppa kommandot, Suspendera eller Hjälp.
Det här alternativet är lite mer flexibelt men innebär att fel gör att ditt skript väntar på din inmatning. Det går bra om du använder PowerShell för att skicka ett e-postmeddelande eller någon annan enkel uppgift, men det kanske inte är något du vill ha när du kör en lång process över natten.
PowerShell Felhantering på ett kraftfullt sätt
Parametern ErrorAction hanterar dina fel på ett okomplicerat sätt. Men om du vill ha lite mer kontroll över felen har PowerShell fortfarande en bra lösning för dig. Med hjälp av Try/Catch kan vi nu förgrena skriptet när cmdlets returnerar ett fel.
Som namnet antyder består Try/Catch av två delar. (Det finns tekniskt sett en tredje, men det kommer vi att ta upp om en stund.) Den första är Try-delen. Du kommer att köra din normala kod i den här delen. Du kommer fortfarande att använda parametern -ErrorAction, men den kan bara ställas in som Stop. Denna flagga säkerställer att din cmdlet utlöser Catch – även om den inte har ett avslutande fel.
Try{
Get-Process "Cortana" -ErrorAction Stop
}
Try kan också förhindra att andra cmdlets körs om sökningen misslyckas. I det här fallet, om du skickade Get-Process-resultaten till Stop-Process, förhindrar en misslyckad sökning att den andra cmdlet körs.
Så nu när du har skapat ett try-block av cmdlets, vad vill du göra när sökningen misslyckas? Med hjälp av Catch half ska du definiera detta.
Catch{
Write-Host "Process Not Found"
}
Precis som med parametern ErrorAction kommer Catch att vara användbart för mer än att ge ett vanligt misslyckande i klartext, särskilt när du gör något lite mer komplext. (I exemplet ovan tvingas felet fram genom att använda appnamnet och inte processnamnet). Så se till att du leker med Try-blocket för att skapa en sökning/åtgärd som du behöver. Du kan använda Catch-blocket för att ditt skript ska skicka e-post till dig om det misslyckas.
Den tredje delen är praktisk om du vill att något ska köras oavsett om din cmdlet lyckas eller inte. För detta kan du använda blocket Finally. Du lägger till detta efter Try och Catch och loggar när ett avsnitt av ditt skript avslutas.
Felvariabeln och loggning
Ditt skript styr nu hur det hanterar fel och hur det reagerar på dem. Du kan använda det som en schemalagd aktivitet, eller åtminstone köra det när du inte sitter vid ditt skrivbord. Men hur kan du undersöka ett misslyckat skript? Med parametern -ErrorVariable skriver din cmdlets fel till en anpassad variabel.
Detta är ett alternativ till systemvariabeln $Error, som innehåller alla fel från den aktuella sessionen.
Din cmdlet behöver bli lite längre. Först definierar du en variabel, något som $SearchError räcker för exemplet. När du kallar SearchError i parametern ErrorVariable använder du inte dollartecknet.
Även om du anropar en variabel som du skapat så anropar du den på grund av hur parametern fungerar utan dollartecken. Lägg sedan till det i slutet av raden.
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Continue -ErrorVariable SearchError
Om du lägger till ett + framför variabelnamnet kan du lägga till variabeln istället för att ersätta den helt och hållet. Det ger dig samma beteende som den globala felvariabeln. Istället kan du använda den här utmatningen och Try/Catch för att skriva anpassad utmatning och tidsstämpla den.
För att få det här att fungera skapar du en textfil direkt efter att du ställt in felvariabeln. Gör detta med cmdlet New-Item. Du kanske vill använda alternativet Inquire för parametern ErrorAction. Då kan du lägga till i en befintlig logg när cmdlet New-Item misslyckas.
$SearchLog = New-Item "~\SearchLog.txt" -type file -ErrorAction Inquire
När du nu bygger ditt Try/Catch-block kan du använda Catch för att logga till en textfil. Du använder Get-Date för att skapa tidsstämpeln. Formateringen kan vara knepig så se till att kopiera den från exemplet.
Try{
Get-ChildItem -Path "~\Documents\*.jpg" -Recurse -ErrorAction Stop -ErrorVariable SearchError
}
Catch{
Add-Content -Path $SearchLog -Value "$(Get-Date -Format dd-MM-yy-hh_mm_ss) Files not found returned error: $SearchError"
}
Upprepa detta vid behov för alla dina cmdlets och du har nu en fin logg över eventuella fel. Om du vill spåra saker som körs framgångsrikt kan du lägga till ett liknande Add-Content i slutet av Try-blocket.
Den här loggningen körs endast när din Try-cmdlet lyckas. Du kan sedan logga dina fel och framgångar med tidsstämplar. Loggningen låter dig nu veta allt som ditt skript har gjort, framgång eller misslyckande.
PowerShell är inte ditt enda alternativ
Även om PowerShell är ett praktiskt verktyg för många Windows-uppgifter kan det vara svårt att lära sig det. Det lämpar sig inte heller för allt. Om du gör systemunderhåll på din dator eller kontrollerar integriteten hos en fil är PowerShell praktiskt. Om du däremot vill köra ett skript för att ladda ner filer från Internet eller någon mer allmän uppgift har du andra alternativ.
Om du till exempel kommer från en Unix- eller Linuxbakgrund kanske du är mer bekväm med att använda bash-skalet. Tack vare Windows Subsystem for Linux kan du nu enkelt använda bash och andra Linuxverktyg på din Windows 10-dator. Om det låter perfekt för dig kan du läsa vår guide för att få igång bash-skalet i Windows 10.
Kris Wouk är musiker, författare och vad det nu kallas när någon gör videor för webben. Han är en teknikentusiast så länge han kan minnas och har definitivt favoritoperativsystem och -enheter, men använder så många andra som möjligt ändå, bara för att hålla sig uppdaterad.
Mer från Kris Wouk