Meester PowerShell Try Catch Blokken met Voorbeelden

Heb je ooit een script of een PowerShell-cmdlet uitgevoerd en werd je geconfronteerd met een schreeuwend muur van tekst – in het rood – zoals hieronder getoond?

Example of errors in PowerShell

Fouten kunnen overweldigend en verwarrend worden. En vooral, fouten zijn vaak moeilijk te lezen, waardoor het bijna onmogelijk is om te bepalen wat en waar het script fout is gegaan.

Gelukkig heb je enkele opties in PowerShell om dit beter te maken via foutafhandeling. Met foutafhandeling kunnen fouten worden gefilterd en weergegeven op een manier die het gemakkelijker maakt om er zin van te maken. En, het begrijpen van de fout maakt het gemakkelijk om meer logica toe te voegen aan foutafhandeling.

In dit artikel leer je over fouten in PowerShell en hoe ze kunnen worden onderschept om foutafhandeling uit te voeren met behulp van de PowerShell Try Catch-blokken (en finally-blokken).

Begrijpen hoe fouten werken in PowerShell

Voordat we ingaan op foutafhandeling, laten we eerst een paar concepten rond fouten in PowerShell behandelen. Het begrijpen van fouten kan leiden tot betere strategieën voor foutafhandeling.

De $Error Automatische Variabele

In PowerShell zijn er veel automatische variabelen, en een daarvan is de $Error automatische variabele. PowerShell gebruikt de $Error variabele om alle fouten op te slaan die in de sessie worden aangetroffen. De $Error variabele is een array van fouten gesorteerd op meest recente.

Wanneer je voor het eerst een PowerShell-sessie opent, is de variabele $Error leeg. Je kunt dit controleren door de variabele $Error aan te roepen.

The $Error variable is empty

Zoals je kunt zien, begint de variabele $Error leeg. Maar, zodra er een fout optreedt, wordt de fout toegevoegd en opgeslagen in de variabele $Error.

In het onderstaande voorbeeld wordt de fout gegenereerd door bewust een servicenaam op te vragen die niet bestaat.

PS> Get-Service xyz
PS> $Error
PS> $Error.Count
The error is added to the $Error variable

Zoals je kunt zien aan de bovenstaande output, werd de gegenereerde fout toegevoegd aan de variabele $Error.

De variabele $Error bevat een verzameling fouten die zijn gegenereerd in de PowerShell-sessie. Elke fout kan worden opgevraagd door de arraypositie aan te roepen. De meest recente fout staat altijd op index 0.

Bijvoorbeeld, de meest recente fout kan worden opgehaald met $Error[0].

De eigenschappen van het object $Error

Aangezien alles in PowerShell een object is, is de variabele $Error een object, en objecten hebben eigenschappen. Door de variabele $Error door te sturen naar de cmdlet Get-Member, zou je de lijst met beschikbare eigenschappen moeten zien.

$Error | Get-Member
The $Error object properties

Om de reden voor de fout te bepalen, kun je de inhoud van de eigenschap InvocationInfo bekijken met het onderstaande commando.

$Error[0].InvocationInfo
The InvocationInfo property

Nu zou je hetzelfde kunnen doen met de andere eigenschappen en ontdekken welke andere informatie je kunt vinden!

Terminale Fouten

Beëindigingsfouten stoppen de uitvoeringsstroom wanneer deze wordt tegengekomen door PowerShell, in tegenstelling tot niet-beëindigingsfouten. Er zijn verschillende manieren waarop een beëindigingsfout kan optreden. Een voorbeeld is wanneer u een cmdlet aanroept met een parameter die niet bestaat.

Zoals u kunt zien aan de onderstaande schermafbeelding, wanneer het commando Get-Process notepad wordt uitgevoerd, is het commando geldig en worden de details van het notepad-proces weergegeven.

The notepad process details

Maar wanneer een parameter die niet bestaat wordt gebruikt, zoals Get-Process notepad -handle 251, geeft de cmdlet een foutmelding dat de handle-parameter niet geldig is. Vervolgens wordt de cmdlet afgesloten zonder de details van het notepad-proces weer te geven.

Error is thrown because the parameter is invalid

Niet-Beëindigingsfouten

Niet-beëindigingsfouten zijn fouten die de uitvoering van het script of commando niet stoppen. Bekijk bijvoorbeeld de onderstaande code. Deze code haalt de lijst met bestandsnamen op uit het bestandslijst.txt-bestand. Vervolgens doorloopt het script elke bestandsnaam, leest de inhoud van elk bestand en geeft deze weer op het scherm.

$file_list =  Get-Content .\filelist.txt
foreach ($file in $file_list) {
    Write-Output "Reading file $file"
    Get-Content $file
}

De inhoud van het bestandslijst.txt-bestand zijn de bestandsnamen die in de onderstaande lijst worden weergegeven.

File_1.log
File_2.log
File_3.log
File_4.log
File_5.log
File_6.log
File_7.log
File_8.log
File_9.log
File_10.log

Maar wat als File_6.log eigenlijk niet bestond? Wanneer u de code uitvoert, zou u verwachten dat er een fout optreedt omdat het script het File_6.log niet kan vinden. U ziet een soortgelijke uitvoer zoals hieronder getoond.

Example of non-terminating error

Zoals je kunt zien aan de screenshot van het bovenstaande resultaat, kon het script de eerste vijf bestanden in de lijst lezen, maar toen het probeerde het bestand File_6.txt, te lezen, trad er een fout op. Het script ging vervolgens door met het lezen van de rest van de bestanden voordat het werd afgesloten. Het heeft niet geëindigd.

De variabele $ErrorActionPreference

Je hebt tot nu toe geleerd over de afsluitende en niet-afsluitende fouten en hoe ze van elkaar verschillen. Maar wist je dat een niet-afsluitende fout kan worden gedwongen om als een afsluitende fout te worden behandeld?

PowerShell heeft een concept genaamd preferentievariabelen. Deze variabelen worden gebruikt om de manier waarop PowerShell op veel verschillende manieren werkt, te wijzigen. Een van deze variabelen is genaamd $ErrorActionPreference.

De variabele $ErrorActionPreference wordt gebruikt om de manier waarop PowerShell niet-afsluitende fouten behandelt, te wijzigen. Standaard is de waarde van $ErrorActionPreference ingesteld op Continue. Door de waarde van de variabele $ErrorActionPreference te wijzigen naar STOP, dwingt PowerShell af dat alle fouten als afsluitende fouten worden behandeld.

Gebruik de onderstaande code om de waarde van $ErrorActionPreference te wijzigen.

$ErrorActionPreference = "STOP"

Om meer te weten te komen over andere geldige waarden van de variabele $ErrorActionPreference, bezoek PowerShell ErrorActionPreference.

Verwijs nu terug naar het voorbeeld gebruikt in het Non-Terminating Errors gedeelte in dit artikel. Het script kan worden aangepast om de wijziging in $ErrorActionPreference op te nemen zoals weergegeven in de onderstaande code:

# Zet de waarde van $ErrorActionPreference op STOP
$ErrorActionPreference = "STOP"
$file_list =  Get-Content .\filelist.txt
foreach ($file in $file_list) {
    Write-Output "Reading file $file"
    Get-Content $file
}

Het uitvoeren van de aangepaste code hierboven zal zich anders gedragen dan voorheen wanneer de waarde van $ErrorActionPreference is ingesteld op de standaardwaarde van Continue.

Forcing a terminating error using the $ErrorActionPreference variable

Zoals te zien is op de screenshot van het resultaat hierboven, kon het script de eerste vijf bestanden in de lijst lezen, maar toen het probeerde het bestand File_6.txt te lezen, trad er een fout op omdat het bestand niet werd gevonden. Vervolgens werd het script beëindigd en werden de overige bestanden niet gelezen.

De waarde van $ErrorActionPreference is alleen geldig in de huidige PowerShell-sessie. Het wordt gereset naar de standaardwaarde zodra een nieuwe PowerShell-sessie wordt gestart.

De Common Parameter ErrorAction

Als de waarde van `$ErrorActionPreference` wordt toegepast op de PowerShell-sessie, is de parameter `ErrorAction` van toepassing op elke cmdlet die algemene parameters ondersteunt. De parameter `ErrorAction` accepteert dezelfde waarden als de variabele `$ErrorActionPreference` doet.

De waarde van de parameter `ErrorAction` heeft voorrang op de waarde van `ErrorActionPreference`.

Laten we teruggaan en dezelfde code gebruiken als in het vorige voorbeeld. Maar deze keer wordt de parameter `ErrorAction` toegevoegd aan de regel `Get-Content`.

# Zet de waarde van $ErrorActionPreference terug naar standaard (CONTINUE)
$ErrorActionPreference = "CONTINUE"
$file_list =  Get-Content .\filelist.txt
foreach ($file in $file_list) {
    Write-Output "Reading file $file"
		# Gebruik de -ErrorAction algemene parameter
		Get-Content $file -ErrorAction STOP
}

Na het uitvoeren van de aangepaste code, zul je zien dat zelfs als `$ErrorActionPreference` is ingesteld op `Continue`, het script nog steeds wordt beëindigd zodra het een fout tegenkomt. Het script wordt beëindigd omdat de PowerShell `ErrorAction` parameterwaarde in `Get-Content` is ingesteld op `STOP`.

Forcing a terminating error using the PowerShell ErrorAction parameter

Gebruik van PowerShell Try Catch Blocks

Op dit punt heb je geleerd over PowerShell-fouten en hoe de variabele `$ErrorActionPreference` en de PowerShell `ErrorAction` parameters werken. Nu is het tijd dat je leert over de goede dingen – de PowerShell `Try Catch Finally` blokken.

$equation$PowerShell \texttt{try catch}$$ blocks (and optional \texttt{finally block}) are een manier om een net om een stuk code te werpen en eventuele fouten die optreden te vangen.

De onderstaande code toont de syntaxis van de \texttt{Try}-verklaring.

try {
    <statement list>
}
catch [[<error type>][',' <error type>]*]{
    <statement list>
}
finally {
    <statement list>
}

De \texttt{Try}-blok bevat de code die je wilt dat PowerShell “probeert” te monitoren op fouten. Als de code in het \texttt{Try}-blok een fout tegenkomt, wordt de fout toegevoegd aan de \texttt{\$Error}-variabele en vervolgens doorgegeven aan het \texttt{Catch}-blok.

Het \texttt{Catch}-blok bevat de acties die moeten worden uitgevoerd wanneer het een fout van het \texttt{Try}-blok ontvangt. Er kunnen meerdere \texttt{Catch}-blokken zijn in een \texttt{Try}-verklaring.

Het \texttt{Finally}-blok bevat de code die aan het einde van de \texttt{Try}-verklaring wordt uitgevoerd. Dit blok wordt uitgevoerd, ongeacht of er een fout is opgetreden.

Het vangen van niet-specifieke fouten (Catch-All) met PowerShell ErrorAction

A simple Try statement contains a Try and a Catch block. The Finally block is optional.

Bijvoorbeeld, om een niet-specifieke uitzondering op te vangen, moet de \texttt{Catch}-parameter leeg zijn. De onderstaande voorbeeldcode maakt gebruik van hetzelfde script dat werd gebruikt in de sectie De \$ErrorActionPreference-variabele, maar is aangepast om de \texttt{Try Catch}-blokken te gebruiken.

Zoals je kunt zien aan de hand van de onderstaande code, is dit keer de \texttt{foreach}-verklaring ingesloten in het \texttt{Try}-blok. Vervolgens bevat een \texttt{Catch}-blok de code om de tekst \texttt{Er is een fout opgetreden} weer te geven als er een fout is opgetreden. De code in het \texttt{Finally}-blok wist gewoon de \texttt{\$Error}-variabele.

$file_list = Get-Content .\filelist.txt
try {
    foreach ($file in $file_list) {
        Write-Output "Reading file $file"
        Get-Content $file -ErrorAction STOP
    }
}
catch {
    Write-Host "An Error Occured" -ForegroundColor RED
}
finally {
    $Error.Clear()
}

De bovenstaande code, nadat het in PowerShell is uitgevoerd, geeft het volgende resultaat.

Script terminated when an error occurred

Het bovenstaande resultaat toont aan dat het script een fout heeft ondervonden, de code binnen het Catch-blok heeft uitgevoerd, en vervolgens is gestopt.

De fout is afgehandeld, wat het doel was van foutafhandeling. Echter, de weergegeven fout was te algemeen. Om een meer beschrijvende fout weer te geven, kunt u toegang krijgen tot de Exception-eigenschap van de fout die is doorgegeven door het Try-blok.

De onderstaande code is aangepast, specifiek de code binnen het Catch-blok, om het uitzonderingsbericht van de huidige fout weer te geven die is doorgegeven via de pijplijn – $PSItem.Exception.Message

$file_list = Get-Content .\filelist.txt
try {
    foreach ($file in $file_list) {
        Write-Output "Reading file $file"
        Get-Content $file -ErrorAction STOP
    }
}
catch {
    Write-Host $PSItem.Exception.Message -ForegroundColor RED
}
finally {
    $Error.Clear()
}

Deze keer, wanneer de gewijzigde code hierboven wordt uitgevoerd, wordt het weergegeven bericht veel meer beschrijvend.

Script terminated with a descriptive error message

Specifieke Fouten Afhandelen

Er zijn momenten waarop een ‘vang alles’ foutafhandeling niet de meest geschikte aanpak is. Misschien wilt u dat uw script een actie uitvoert die afhankelijk is van het type fout dat wordt aangetroffen.

Hoe bepaalt u het fouttype? Door de TypeName-waarde van de Exception-eigenschap van de laatste fout te controleren. Om bijvoorbeeld het fouttype uit het vorige voorbeeld te vinden, gebruikt u deze opdracht:

$Error[0].Exception | Get-Member

Het resultaat van de bovenstaande code zou eruitzien als de onderstaande screenshot. Zoals u kunt zien, wordt de TypeName-waarde weergegeven – System.Management.Automation.ItemNotFoundException.

Getting the error TypeName value

Nu je het fouttype kent dat je moet onderscheppen, wijzig je de code om het specifiek te vangen. Zoals je kunt zien in de aangepaste code hieronder, zijn er nu twee `Catch`-blokken. Het eerste `Catch`-blok onderschept een specifiek type fout (`System.Management.Automation.ItemNotFoundException`). Daarentegen bevat het tweede `Catch`-blok het generieke, vang-alles foutbericht.

$file_list = Get-Content .\filelist.txt
try {
    foreach ($file in $file_list) {
        Write-Output "Reading file $file"
        Get-Content $file -ErrorAction STOP
    }
}
catch [System.Management.Automation.ItemNotFoundException]{
    Write-Host "The file $file is not found." -ForegroundColor RED
}
catch {
    Write-Host $PSItem.Exception.Message -ForegroundColor RED
}
finally {
    $Error.Clear()
}

De onderstaande schermafbeelding toont de uitvoer van de hierboven aangepaste code.

Script terminated with a specific error message

Conclusie

In dit artikel heb je geleerd over fouten in PowerShell, de eigenschappen ervan, en hoe je het specifieke type fout kunt bepalen. Je hebt ook het verschil geleerd tussen hoe de variabele `$ErrorActionPreference` en de PowerShell `ErrorAction`-parameter bepalen hoe PowerShell niet-terminale fouten behandelt.

Je hebt ook geleerd hoe je de PowerShell `Try Catch Finally`-blokken kunt gebruiken voor foutafhandeling, zowel voor specifieke fouten als voor een vang-alles benadering.

De voorbeelden die in dit artikel worden getoond, demonstreren alleen de basisprincipes van hoe de `Try Catch Finally`-blokken werken. De kennis die ik hoop dat je hebt opgedaan in dit artikel zou je de startblokken moeten geven om foutafhandeling toe te passen in je scripts.

Verder lezen

Source:
https://adamtheautomator.com/powershell-try-catch/