about_Error_Handling

Kort beskrivning

Beskriver typerna av fel i PowerShell och mekanismerna för att hantera dem.

Lång beskrivning

PowerShell särskiljer tre felkategorier:

  • Icke-avslutande fel
  • Instruktionsslutfel
  • Skriptslutfel

Att förstå skillnaden är viktigt för att skriva tillförlitliga skript och moduler, eftersom varje kategori har olika standardbeteende och kräver olika hanteringstekniker.

Dessutom rapporterar externa (inbyggda) program fel via slutkoder, som PowerShell spårar separat från sitt eget felsystem.

Typer av fel

Icke-avslutande fel

Ett icke-avslutande fel rapporterar ett problem men stoppar inte pipelinen. Kommandot fortsätter att bearbeta efterföljande indataobjekt. Icke-avslutande fel genereras av:

  • Cmdlet Write-Error
  • Metoden $PSCmdlet.WriteError() i avancerade funktioner
  • Cmdletar som påträffar återställningsbara fel på enskilda indataobjekt

Som standard visar PowerShell felmeddelandet och fortsätter körningen.

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

I det här exemplet Get-Content rapporterar ett icke-avslutande fel för noSuchFile.txt och fortsätter sedan bearbetningen file3.txt.

Icke-avslutande fel utlöses catchinte eller trap som standard.

Instruktionsslutfel

Ett instruktionsslutfel hindrar den aktuella instruktionen (pipelinen) från att köras, men körningen fortsätter vid nästa instruktion i skriptet. Instruktionsslutfel genereras av:

  • Metoden $PSCmdlet.ThrowTerminatingError() i avancerade funktioner och kompilerade cmdletar
  • Motorfel som CommandNotFoundException (anropar ett kommando som inte finns) och ParameterBindingException (ogiltiga parameterargument)
  • .NET-metodanrop som utlöser undantag, till exempel [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'

Instruktionsslutfel kan fångas av try/catch och trap.

Anmärkning

.ThrowTerminatingError() läser inte parametern -ErrorAction (förutom värdet Break som anger felsökaren). Gäller dock $ErrorActionPreference för instruktionsslutfel via motorns instruktionsnivåhanterare. Kan till exempel $ErrorActionPreference = 'SilentlyContinue' förhindra ett instruktionsslutfel så att skriptet fortsätter vid nästa instruktion. Parametern -ErrorAction kan inte göra detta. Mer information finns i asymmetrin $ErrorActionPreference.

Skriptslutfel

Ett skriptslutfel avbryter hela anropsstacken. Körningen stoppas helt om inte felet fångas av ett block eller trap en try/catch -instruktion. Skriptslutfel genereras av:

  • Nyckelordet throw
  • Parsa fel (syntaxfel som förhindrar att skriptet kompileras)
  • Icke-avslutande fel eskaleras av -ErrorAction Stop eller $ErrorActionPreference = 'Stop' i icke-avancerade kontexter. Mer information finns i Så här fungerar eskalering.
  • Vissa kritiska motorfel
# 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)'

Nyckelordet throw genererar ett skriptslutfel som standard. Kan dock $ErrorActionPreference utelämna throw när det är inställt på SilentlyContinue eller .Ignore När du anropar en avancerad funktion med -ErrorAction SilentlyContinueöversätts parametern till ett omfångslokalt $ErrorActionPreference värde, så den undertrycker throw även inuti den funktionen.

Anmärkning

Även med $ErrorActionPreference = 'Ignore', en throw som ignoreras registrerar fortfarande en post i $Error. Värdet Ignore förhindrar $Error endast registrering för icke-avslutande fel.

Viktigt!

Termerna statement-terminating och script-terminating beskriver effektens omfattning, inte felets allvarlighetsgrad. Ett instruktionsslutfel stoppar en instruktion. Ett skriptslutfel stoppar hela skriptet och dess anropare. Båda kan fångas av try/catch.

Externa programfel

Externa (interna) program deltar inte direkt i PowerShells felsystem. De rapporterar fel via en slutkod som inte är noll, som PowerShell lagrar i den $LASTEXITCODE automatiska variabeln.

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

Som standard en slutkod som inte är noll från ett internt program:

  • Anger $? till $false
  • Genererar inte en ErrorRecord i $Error
  • Utlöses catchinte ellertrap

PowerShell 7.3 lade till den experimentella inställningsvariabeln $PSNativeCommandUseErrorActionPreference, som blev en stabil funktion i 7.4. När du anger den här variabeln till $trueorsakar det en slutkod som inte är noll för att generera ett icke-avslutande fel vars meddelande anger den specifika slutkoden (a NativeCommandExitException). Det här felet respekterar $ErrorActionPreference, så om du ställer in det på Stop befordras felet till ett skriptslutfel som kan fångas med/trycatch .

Feltillståndsvariabler

PowerShell har flera automatiska variabler som återspeglar det aktuella feltillståndet.

$?

Innehåller $true om den senaste åtgärden lyckades och $false om det uppstod något fel (icke-avslutande eller avslutande). För interna kommandon $? anges baserat på slutkoden: $true för slutkod 0, $false annars.

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

$Error

En ArrayList som lagrar de senaste felposterna, med det senaste felet vid index .0 Listan innehåller upp till $MaximumErrorCount poster (standard 256).

Alla avslutande fel läggs till i $Error. För att avsluta fel Ignore undertrycker visning men registrerar fortfarande felet i $Error. Alla icke-avslutande läggs till $Error om inte -ErrorAction Ignore används vid icke-avslutande fel, vilket förhindrar både visning och inspelning.

$LASTEXITCODE

Innehåller slutkoden för det senaste interna programmet som kördes. Ett värde för 0 konventionellt indikerar framgång. Alla värden som inte är noll indikerar fel. Den här variabeln påverkas inte av PowerShell-cmdlet-fel.

Kontrollera felbeteende

Den -ErrorAction gemensamma parametern

Den -ErrorAction vanliga parametern åsidosätter $ErrorActionPreference för ett enda kommando. Den styr hur PowerShell svarar på icke-avslutande fel från det kommandot.

Värde Beteende
Continue Visa felet och fortsätt (standard)
SilentlyContinue Ignorera visning, lägg till i $Error, fortsätt
Ignore Ignorera visning och lägg inte till i $Error
Stop Eskalera till ett avslutande fel (se Så här fungerar eskalering)
Inquire Fråga användaren om ett beslut
Break Ange felsökningsprogrammet

-ErrorAction ändrar inte beteendet för fel som genereras av $PSCmdlet.ThrowTerminatingError(). Dessa fel är alltid instruktionsslutande oavsett uppringarens önskemål.

Variabeln $ErrorActionPreference

Inställningsvariabeln $ErrorActionPreference gäller för alla kommandon i det aktuella omfånget och underordnade omfång. Den accepterar samma värden som -ErrorAction.

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

När -ErrorAction har angetts för ett kommando har det företräde framför $ErrorActionPreference det kommandot.

Så här fungerar eskalering

När -ErrorAction Stop eller $ErrorActionPreference = 'Stop' är i kraft konverterar PowerShell icke-avslutande fel till avslutande fel med hjälp av följande mekanism:

  1. En cmdlet anropar WriteError() internt för att generera ett icke-avslutande fel.
  2. Motorn kontrollerar den effektiva ErrorAction inställningen för kommandot.
  3. Eftersom inställningen är Stopskapar motorn en ActionPreferenceStopException som omsluter den ursprungliga felposten.
  4. Om den fångas av catchär den ursprungliga felinformationen tillgänglig via $_.Exception.ErrorRecord.

Omfattningen för det eskalerade felet beror på kontexten:

  • I icke-avancerade skript, funktioner eller skriptblock eskaleras inställningen $ErrorActionPreference = 'Stop' till ett skriptslutfel . Felet sprider upp anropsstacken.
  • I avancerade funktioner och skriptblock (de med [CmdletBinding()]) förblir felet instruktionsslutande. Körningen fortsätter vid nästa instruktion efter anropet.
  • Att skicka -ErrorAction Stop till en avancerad funktion har samma effekt som inställningen $ErrorActionPreference = 'Stop' i den, eftersom -ErrorAction det översätts till ett omfångslokalt $ErrorActionPreference värde.

Eskaleringsexempel

  • Icke-avancerat: skriptavslutande ("efter" skrivs INTE ut)

    & {
        param()
        $ErrorActionPreference = 'Stop'
        Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • AVANCERAT: instruktionsavslutande ("efter" SKRIVS UT)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • Utan -ErrorAction Stop: icke-avslutande körs inte catch

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Med -ErrorAction Stop: eskalerad till avslutande

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

Eskalerade fel kan fångas av den ursprungliga undantagstypen. Motorn skriver upp ActionPreferenceStopException för att hitta det underliggande undantaget:

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

Asymmetrin $ErrorActionPreference

Parametern -ErrorAction och variabeln $ErrorActionPreference beter sig annorlunda med avslutande fel. Det är viktigt att förstå den här asymmetrin:

  • -ErrorAction påverkar endast icke-avslutande fel. När en cmdlet anropar $PSCmdlet.ThrowTerminatingError()ignoreras parametern -ErrorAction (förutom Break, som anger felsökaren). Felet genereras alltid.

  • $ErrorActionPreference påverkar både icke-avslutande och instruktionsslutande fel. Motorns felhanterare på instruktionsnivå läser $ErrorActionPreference (inte parametern -ErrorAction ) och kan utelämna ett instruktionsslutfel när värdet är SilentlyContinue eller Ignore.

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'

Viktigt!

$ErrorActionPreference kan inte utelämna fel som har SuppressPromptInInterpreter angetts till true. Dessa sprids alltid oavsett inställningsvariabeln. Exempel på den här typen av fel är:

  • ActionPreferenceStopException från -ErrorAction Stop eskalering
  • Fel i PowerShell-klassmetoder
  • PipelineStoppedException

Hantering av fel

try/catch/finally

Använd try/catch/finally för att hantera instruktionsterminerings- och skriptslutfel. När ett fel inträffar i ett try block söker PowerShell efter ett matchande catch block. Blocket finally körs alltid, oavsett om ett fel uppstod eller inte.

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
}

I ett try block anger motorn en intern flagga som gör att icke-avslutande fel eskaleras av -ErrorAction Stop eller $ErrorActionPreference = 'Stop' sprids till catch blocket. Detta är utformat beteende, inte ett specialfall.

Fullständig syntaxinformation finns i about_Try_Catch_Finally.

trap

Instruktionen trap hanterar avslutande fel på omfångsnivå. När ett fel inträffar någonstans i omfånget trap för omslutning körs blocket.

  • Standard (nej break eller continue): Felet visas och körningen fortsätter vid nästa instruktion efter den som orsakade felet.
  • continue i trap: Undertrycker felmeddelandet och återupptas vid nästa instruktion.
  • break i trap: Felet sprids till det överordnade omfånget.
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'

Fullständig syntaxinformation finns i about_Trap.

Rapportera fel i funktioner och skript

När du skriver funktioner och skript väljer du den felrapporteringsmekanism som matchar felets allvarlighetsgrad.

Icke-avslutande – använd Write-Error

Använd Write-Error när funktionen kan fortsätta bearbeta andra indata. Detta är lämpligt för pipelinefunktioner som bearbetar flera objekt och stöter på fel på enskilda objekt.

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

Anmärkning

I avancerade funktioner (de med [CmdletBinding()]) använder du $PSCmdlet.WriteError() i stället för Write-Error att se till $false att det $? är korrekt inställt på i anroparens omfång. Cmdleten Write-Error är inte alltid korrekt inställd $? .

Instruktionsslutande – använd $PSCmdlet.ThrowTerminatingError()

Använd $PSCmdlet.ThrowTerminatingError() när funktionen inte kan fortsätta alls, men anroparen bör bestämma hur felet ska hanteras. Detta är den rekommenderade metoden i avancerade funktioner.

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
}

När felet lämnar funktionen behandlar anroparen det som ett icke-avslutande fel som standard. Anroparen kan eskalera den med -ErrorAction Stop.

Skriptslutning – använd throw

Använd throw när återställning inte är möjligt och hela skriptet ska stoppas.

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

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

Vilken mekanism som ska användas

  • När du bearbetar flera indata där vissa kan misslyckas använder du Write-Error eller $PSCmdlet.WriteError().
  • Om funktionen inte kan fortsätta använder $PSCmdlet.ThrowTerminatingError() du och låter anroparen bestämma hur den ska hanteras.
  • Om hela skriptet måste stoppas omedelbart använder du throw.

Sammanfattning av feltyper

I följande tabeller sammanfattas egenskaperna och beteendet för de olika feltyperna i PowerShell.

Icke-avslutande fel

Icke-avslutande fel kan genereras av Write-Error eller $PSCmdlet.WriteError().

Attribute Beskrivning
Påverkans omfattning Pipelinen fortsätter
Fångad av catch Nej (om inte eskalerat)
Fångad av trap Nej (om inte eskalerat)
Har lagts till i $Error Ja (om inte Ignore)
Anger $? till $false Ja
Påverkas av -ErrorAction Ja
Påverkas av $ErrorActionPreference Ja

Instruktionsslutfel

Instruktionsslutfel kan genereras av ThrowTerminatingError(), motorfel, .NET-metodfel eller -ErrorAction Stop i avancerade kontexter.

Attribute Beskrivning
Påverkans omfattning Aktuell instruktion stoppas; skriptet fortsätter
Fångad av catch Ja
Fångad av trap Ja
Har lagts till i $Error Ja
Anger $? till $false Ja
Påverkas av -ErrorAction Nej (Break endast)
Påverkas av $ErrorActionPreference Ja (kan undertrycka)

Skriptslutfel

Skriptslutfel kan genereras av throw, parsa fel eller -ErrorAction Stop i icke-avancerade kontexter.

Attribute Beskrivning
Påverkans omfattning Varva ned samtalsstacken
Fångad av catch Ja
Fångad av trap Ja
Har lagts till i $Error Ja
Anger $? till $false Ja
Påverkas av -ErrorAction No
Påverkas av $ErrorActionPreference throw: Ja (kan undertrycka)
Påverkas av $ErrorActionPreference Eskalerad: beror på kontext

Se även