about_Error_Handling

Korte beschrijving

Beschrijft de typen fouten in PowerShell en de mechanismen voor het afhandelen ervan.

Lange beschrijving

PowerShell onderscheidt drie soorten fouten:

  • Niet-afsluitfouten
  • Fouten bij het beëindigen van instructies
  • Fouten bij het beëindigen van scripts

Het begrijpen van het onderscheid is essentieel voor het schrijven van betrouwbare scripts en modules, omdat elke categorie verschillend standaardgedrag heeft en verschillende afhandelingstechnieken vereist.

Bovendien melden externe (systeemeigen) programma's een fout via afsluitcodes, die PowerShell afzonderlijk van zijn eigen foutsysteem bijhoudt.

Soorten fouten

Niet-afsluitfouten

Een niet-afsluitfout meldt een probleem, maar stopt de pijplijn niet. De opdracht gaat verder met het verwerken van volgende invoerobjecten. Niet-afsluitfouten worden gegenereerd door:

  • De Write-Error cmdlet
  • De $PSCmdlet.WriteError() methode in geavanceerde functies
  • Cmdlets die kunnen worden hersteld voor afzonderlijke invoerobjecten

Standaard wordt in PowerShell het foutbericht weergegeven en wordt de uitvoering voortgezet.

# Non-terminating error: the pipeline continues after the failure
'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object {
    Get-Content $_ -ErrorAction Continue
}

In dit voorbeeld Get-Content wordt een niet-afsluitfout gerapporteerd voor noSuchFile.txt en wordt vervolgens de verwerking file3.txtvoortgezet.

Niet-afsluitfouten worden niet geactiveerd catch of trap standaard.

Fouten bij het beëindigen van instructies

Een instructie-afsluitfout voorkomt dat de huidige instructie (pijplijn) wordt uitgevoerd, maar de uitvoering wordt voortgezet bij de volgende instructie in het script. Fouten bij het beëindigen van instructies worden gegenereerd door:

  • De $PSCmdlet.ThrowTerminatingError() methode in geavanceerde functies en gecompileerde cmdlets
  • Enginefouten zoals CommandNotFoundException (aanroepen van een opdracht die niet bestaat) en ParameterBindingException (ongeldige parameterargumenten)
  • .NET-methode roept uitzonderingen op, zoals [int]::Parse('abc')
# Statement-terminating error: Get-Item fails, but the next statement runs
Get-Item -Path 'C:\NoSuchFile.txt'
Write-Output 'This still runs'

Fouten bij het beëindigen van instructies kunnen worden ondervangen door try/catch en trap.

Opmerking

.ThrowTerminatingError() raadpleegt -ErrorAction de parameter niet (met uitzondering van de Break waarde die het foutopsporingsprogramma invoert). $ErrorActionPreference Is echter van toepassing op instructie-afsluitfouten via de handler op instructieniveau van de engine. Kan bijvoorbeeld $ErrorActionPreference = 'SilentlyContinue' een instructie-afsluitfout onderdrukken, zodat het script bij de volgende instructie wordt voortgezet. De -ErrorAction parameter kan dit niet doen. Zie de $ErrorActionPreference asymmetrie voor meer informatie.

Fouten bij het beëindigen van scripts

Een script-afsluitfout verwikkelt de volledige aanroepstack. Uitvoering stopt volledig tenzij de fout wordt opgevangen door een try/catch blok of trap instructie. Scripteindfouten worden gegenereerd door:

  • Het throw-trefwoord
  • Fouten parseren (syntaxisfouten die verhinderen dat het script wordt gecompileerd)
  • Niet-afsluitfouten geëscaleerd door -ErrorAction Stop of $ErrorActionPreference = 'Stop' in niet-geavanceerde contexten. Zie Hoe escalatie werkt voor meer informatie.
  • Bepaalde kritieke enginefouten
# Script-terminating error: throw unwinds the call stack
function Test-Throw {
    throw 'Critical failure'
    Write-Output 'This never runs'
}

Test-Throw
Write-Output 'This never runs either (unless caught)'

Met throw het trefwoord wordt standaard een scripteindfout gegenereerd. $ErrorActionPreference Kan echter onderdrukken throw wanneer deze is ingesteld op SilentlyContinue of Ignore. Wanneer u een geavanceerde functie aanroept, -ErrorAction SilentlyContinuewordt de parameter omgezet in een bereik-lokale $ErrorActionPreference waarde, zodat deze ook in die functie wordt onderdrukt throw .

Opmerking

Zelfs met $ErrorActionPreference = 'Ignore', een throw die wordt onderdrukt, registreert nog steeds een vermelding in $Error. De Ignore waarde voorkomt alleen het $Error opnemen van niet-afsluitfouten .

Belangrijk

In de termen voor het beëindigen van de instructie en scripteinding wordt het bereik van de impact beschreven, niet de ernst van de fout. Een instructie-afsluitfout stopt één instructie. Een script-afsluitfout stopt het hele script en de aanroepers. Beide kunnen worden gevangen door try/catch.

Fouten in externe programma's

Externe (systeemeigen) programma's nemen niet rechtstreeks deel aan het foutsysteem van PowerShell. Ze melden fouten via een afsluitcode die niet nul is, die in PowerShell wordt opgeslagen in de $LASTEXITCODE automatische variabele.

git clone https://example.com/nonexistent.git 2>$null
if ($LASTEXITCODE -ne 0) {
    Write-Error "git failed with exit code $LASTEXITCODE"
}

Standaard is een niet-nul afsluitcode van een systeemeigen programma:

  • Hiermee wordt ingesteld $? op $false
  • Genereert geenErrorRecord in $Error
  • Wordt niet geactiveerd catch of trap

PowerShell 7.3 heeft de experimentele voorkeursvariabele $PSNativeCommandUseErrorActionPreferencetoegevoegd, die een stabiele functie werd in 7.4. Wanneer u deze variabele $trueinstelt op, wordt er een afsluitcode die niet nul is, een niet-afsluitfout verzonden waarvan het bericht de specifieke afsluitcode (a NativeCommandExitException) aangeeft. Deze fout respecteert$ErrorActionPreference, dus het instellen ervan om de fout te Stop bevorderen op een script-afsluitfout die kan worden opgevangen met/trycatch .

Foutstatusvariabelen

PowerShell onderhoudt verschillende automatische variabelen die de huidige foutstatus weerspiegelen.

$?

Bevat $true of de laatste bewerking is geslaagd en $false of er een fout is opgetreden (niet-afsluiten of beëindigen). Voor systeemeigen opdrachten $? wordt ingesteld op basis van de afsluitcode: $true voor afsluitcode 0, $false anders.

Get-Item -Path 'C:\NoSuchFile.txt' 2>$null
$?  # False

$Error

Een ArrayList record waarin de meest recente foutrecords worden opgeslagen, met de meest recente fout bij de index 0. De lijst bevat maximaal $MaximumErrorCount vermeldingen (standaard 256).

Alle afsluitfouten worden toegevoegd aan $Error. Voor afsluitfouten Ignore onderdrukt u de weergave, maar registreert u de fout nog steeds in $Error. Alle niet-afsluitfouten worden toegevoegd aan $Error tenzij -ErrorAction Ignore ze worden gebruikt bij niet-afsluitfouten, waardoor zowel weergave als opname worden voorkomen.

$LASTEXITCODE

Bevat de afsluitcode van het laatste systeemeigen programma dat is uitgevoerd. Een waarde van 0 conventioneel duidt op succes. Elke waarde die niet nul is, geeft aan dat de fout is mislukt. Deze variabele wordt niet beïnvloed door PowerShell-cmdlet-fouten.

Gedrag van besturingsfouten

De -ErrorAction algemene parameter

De -ErrorAction algemene parameter overschrijft $ErrorActionPreference voor één opdracht. Het bepaalt hoe PowerShell reageert op niet-afsluitfouten van die opdracht.

Waarde Gedrag
Continue De fout weergeven en doorgaan (standaard)
SilentlyContinue Weergave onderdrukken, toevoegen aan $Error, doorgaan
Ignore Weergave onderdrukken en niet toevoegen aan $Error
Stop Escaleren naar een afsluitfout (zie Hoe escalatie werkt)
Inquire De gebruiker vragen om een beslissing
Break Voer het foutopsporingsprogramma in

-ErrorAction wijzigt het gedrag van fouten die worden gegenereerd door $PSCmdlet.ThrowTerminatingError(). Deze fouten zijn altijd instructie-afsluit, ongeacht de voorkeur van de beller.

De $ErrorActionPreference variabele

De $ErrorActionPreference voorkeursvariabele is van toepassing op alle opdrachten in het huidige bereik en onderliggende bereiken. Deze accepteert dezelfde waarden als -ErrorAction.

$ErrorActionPreference = 'Stop'
# All non-terminating errors in this scope now become terminating
Write-Error 'This now throws'   # Generates ActionPreferenceStopException

Wanneer -ErrorAction wordt opgegeven voor een opdracht, heeft deze voorrang op $ErrorActionPreference die opdracht.

Hoe escalatie werkt

Wanneer -ErrorAction Stop of $ErrorActionPreference = 'Stop' in werking is, converteert PowerShell niet-afsluitfouten naar afsluitfouten met behulp van het volgende mechanisme:

  1. Een cmdlet roept WriteError() intern aan om een niet-afsluitfout te verzenden.
  2. De engine controleert de effectieve ErrorAction voorkeur voor de opdracht.
  3. Omdat de voorkeur is Stop, maakt de engine een ActionPreferenceStopException die de oorspronkelijke foutrecord verpakt.
  4. Als dit wordt onderschept catch, is de oorspronkelijke foutinformatie toegankelijk via $_.Exception.ErrorRecord.

Het bereik van de geëscaleerde fout is afhankelijk van de context:

  • Bij niet-geavanceerde scripts, functies of scriptblokken escaleert het instellen $ErrorActionPreference = 'Stop' van escalatie naar een fout bij het beëindigen van scripts. De fout wordt doorgegeven aan de aanroepstack.
  • In geavanceerde functies en scriptblokken (met) [CmdletBinding()]blijft de fout instructie-afsluiter. Uitvoering wordt voortgezet bij de volgende instructie na de aanroep.
  • Het doorgeven -ErrorAction Stop aan een geavanceerde functie heeft hetzelfde effect als de instelling $ErrorActionPreference = 'Stop' erin, omdat -ErrorAction deze wordt omgezet in een bereik-lokale $ErrorActionPreference waarde.

Voorbeelden van escalatie

  • NIET-geavanceerd: scripteinden ('after' wordt NIET afgedrukt)

    & {
        param()
        $ErrorActionPreference = 'Stop'
        Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • GEAVANCEERD: statement-terminating ('after' DOES print)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • Zonder -ErrorAction Stop: niet-afsluiten, wordt catch niet uitgevoerd

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Met -ErrorAction Stop: geëscaleerd naar beëindiging

    try {
        Write-Error 'This becomes terminating' -ErrorAction Stop
    } catch {
        Write-Output "Caught: $_"   # Reached
    }
    

Geëscaleerde fouten kunnen worden opgevangen door het oorspronkelijke uitzonderingstype. De engine pakt de ActionPreferenceStopException onderliggende uitzondering uit:

try {
    Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
    Write-Output "File not found: $($_.Exception.Message)"
}

De $ErrorActionPreference asymmetrie

De -ErrorAction parameter en de $ErrorActionPreference variabele gedragen zich anders met afsluitfouten. Het is belangrijk om deze asymmetrie te begrijpen:

  • -ErrorAction is alleen van invloed op niet-afsluitfouten . Wanneer een cmdlet wordt aangeroepen $PSCmdlet.ThrowTerminatingError(), wordt de -ErrorAction parameter genegeerd (met uitzondering van Break, waarmee het foutopsporingsprogramma wordt ingevoerd). De fout wordt altijd gegenereerd.

  • $ErrorActionPreference is van invloed op zowel niet-afsluit- als instructie-afsluitfouten. De fouthandler op instructieniveau van de engine leest $ErrorActionPreference (niet de -ErrorAction parameter) en kan een instructiebeëindigingsfout onderdrukken wanneer de waarde of SilentlyContinueIgnore.

function Test-Asymmetry {
    [CmdletBinding()]
    param()
    $er = [System.Management.Automation.ErrorRecord]::new(
        [System.InvalidOperationException]::new('test error'),
        'TestError',
        [System.Management.Automation.ErrorCategory]::InvalidOperation,
        $null
    )
    $PSCmdlet.ThrowTerminatingError($er)
}

# -ErrorAction SilentlyContinue does NOT suppress the error:
Test-Asymmetry -ErrorAction SilentlyContinue   # Error is still thrown

# $ErrorActionPreference DOES suppress the error:
$ErrorActionPreference = 'SilentlyContinue'
Test-Asymmetry   # Error is silently suppressed, script continues
$ErrorActionPreference = 'Continue'

Belangrijk

$ErrorActionPreference kan fouten die zijn SuppressPromptInInterpreter ingesteld trueop . Deze worden altijd doorgegeven, ongeacht de voorkeursvariabele. Voorbeelden van dit type fout zijn:

  • ActionPreferenceStopException van -ErrorAction Stop escalatie
  • Fouten in PowerShell-klassemethoden
  • PipelineStoppedException

Afhandeling van fouten

try/catch/finally

Gebruik try/catch/finally dit voor het afhandelen van fouten bij het beëindigen van instructies en het beëindigen van scripts. Wanneer er een fout optreedt in een try blok, zoekt PowerShell naar een overeenkomend catch blok. Het finally blok wordt altijd uitgevoerd, ongeacht of er een fout is opgetreden.

try {
    $result = Get-Content -Path 'data.txt' -ErrorAction Stop
}
catch [System.Management.Automation.ItemNotFoundException] {
    Write-Warning 'Data file not found, using defaults.'
    $result = 'default'
}
catch {
    Write-Warning "Unexpected error: $_"
}
finally {
    Write-Verbose 'Cleanup complete.' -Verbose
}

Binnen een try blok stelt de engine een interne vlag in die niet-afsluitfouten veroorzaakt die zijn geëscaleerd door -ErrorAction Stop of $ErrorActionPreference = 'Stop' om door te geven aan het catch blok. Dit is ontworpen gedrag, geen speciaal geval.

Zie about_Try_Catch_Finally voor volledige syntaxisdetails.

trap

De trap instructie verwerkt afsluitfouten op bereikniveau. Wanneer er een fout optreedt ergens in het bereik insluiten, wordt het trap blok uitgevoerd.

  • Standaard (nee break of continue): de fout wordt weergegeven en de uitvoering wordt voortgezet op de volgende instructie na de instructie die de fout heeft veroorzaakt.
  • continue in de trap: onderdrukt het foutbericht en hervat bij de volgende instructie.
  • break in de trap: de fout wordt doorgegeven aan het bovenliggende bereik.
trap [System.Management.Automation.CommandNotFoundException] {
    Write-Warning "Command not found: $($_.TargetObject)"
    continue
}

NonsenseCommand   # Trap fires, execution continues
Write-Output 'This runs because the trap used continue'

Zie about_Trap voor volledige syntaxisdetails.

Fouten rapporteren in functies en scripts

Kies bij het schrijven van functies en scripts het mechanisme voor foutrapportage dat overeenkomt met de ernst van de fout.

Niet-afsluiten - gebruik Write-Error

Gebruik Write-Error deze functie wanneer de functie andere invoer kan blijven verwerken. Dit is geschikt voor pijplijnfuncties die meerdere objecten verwerken en fouten ondervinden voor afzonderlijke items.

function Test-Path-Safe {
    [CmdletBinding()]
    param([Parameter(ValueFromPipeline)][string]$Path)
    process {
        if (-not (Test-Path $Path)) {
            Write-Error "Path not found: $Path"
            return
        }
        $Path
    }
}

Opmerking

Gebruik in geavanceerde functies (die met [CmdletBinding()]), $PSCmdlet.WriteError() in plaats van Write-Error ervoor te zorgen dat deze $? juist is ingesteld $false in het bereik van de aanroeper. De Write-Error cmdlet is niet altijd correct ingesteld $? .

Instructie-afsluit - gebruik $PSCmdlet.ThrowTerminatingError()

Gebruik $PSCmdlet.ThrowTerminatingError() deze functie als de functie helemaal niet kan doorgaan, maar de aanroeper moet beslissen hoe de fout moet worden afgehandeld. Dit is de aanbevolen benadering in geavanceerde functies.

function Get-Config {
  [CmdletBinding()]
  param([string]$Path)

  if (-not (Test-Path $Path)) {
    $er = [System.Management.Automation.ErrorRecord]::new(
      [System.IO.FileNotFoundException]::new("Config file not found: $Path"),
      'ConfigNotFound',
      [System.Management.Automation.ErrorCategory]::ObjectNotFound,
      $Path
    )
    $PSCmdlet.ThrowTerminatingError($er)
  }

  Get-Content $Path | ConvertFrom-Json
}

Nadat de fout de functie verlaat, behandelt de aanroeper deze standaard als een niet-afsluitfout. De beller kan het escaleren met -ErrorAction Stop.

Scriptafeinding - gebruik throw

Gebruik throw dit wanneer herstel niet mogelijk is en het hele script moet stoppen.

$config = Get-Content 'config.json' -ErrorAction SilentlyContinue |
    ConvertFrom-Json

if (-not $config) {
    throw 'Cannot proceed without a valid configuration file.'
}

Welk mechanisme moet worden gebruikt

  • Wanneer u meerdere invoergegevens verwerkt waarbij sommige mogelijk mislukken, gebruikt Write-Error of $PSCmdlet.WriteError().
  • Als de functie niet kan doorgaan, gebruikt $PSCmdlet.ThrowTerminatingError() u deze en laat u de aanroeper beslissen hoe deze moet worden afgehandeld.
  • Als het hele script onmiddellijk moet stoppen, gebruikt u throw.

Samenvatting van fouttypen

De volgende tabellen bevatten een overzicht van de eigenschappen en het gedrag van de verschillende fouttypen in PowerShell.

Fout bij niet-beëindigen

Niet-afsluitfouten kunnen worden gegenereerd door Write-Error of $PSCmdlet.WriteError().

Attribute Beschrijving
Bereik van impact Pijplijn wordt voortgezet
Gevangen door catch Nee (tenzij geëscaleerd)
Gevangen door trap Nee (tenzij geëscaleerd)
Toegevoegd aan $Error Ja (tenzij Ignore)
Hiermee wordt ingesteld $? op $false Ja
Beïnvloed door -ErrorAction Ja
Beïnvloed door $ErrorActionPreference Ja

Instructie-afsluitfout

Fouten bij het beëindigen van instructies kunnen worden gegenereerd door ThrowTerminatingError(), enginefouten, .NET-methodeuitzonderingen of -ErrorAction Stop in geavanceerde contexten.

Attribute Beschrijving
Bereik van impact Huidige instructie stopt; script wordt voortgezet
Gevangen door catch Ja
Gevangen door trap Ja
Toegevoegd aan $Error Ja
Hiermee wordt ingesteld $? op $false Ja
Beïnvloed door -ErrorAction Nee (Break alleen)
Beïnvloed door $ErrorActionPreference Ja (kan onderdrukken)

Fout bij afsluiten van script

Scripteindfouten kunnen worden gegenereerd door throw, fouten parseren of -ErrorAction Stop in niet-geavanceerde contexten.

Attribute Beschrijving
Bereik van impact Oproepstack komt tot rust
Gevangen door catch Ja
Gevangen door trap Ja
Toegevoegd aan $Error Ja
Hiermee wordt ingesteld $? op $false Ja
Beïnvloed door -ErrorAction No
Beïnvloed door $ErrorActionPreference throw: Ja (kan onderdrukken)
Beïnvloed door $ErrorActionPreference Geëscaleerd: afhankelijk van context

Zie ook