about_Error_Handling

Krátký popis

Popisuje typy chyb v PowerShellu a mechanismy pro jejich zpracování.

Dlouhý popis

PowerShell rozlišuje tři kategorie chyb:

  • Neukončující chyby
  • Chyby ukončující příkazy
  • Chyby ukončující skripty

Pochopení rozdílu je nezbytné pro psaní spolehlivých skriptů a modulů, protože každá kategorie má jiné výchozí chování a vyžaduje různé techniky zpracování.

Kromě toho externí (nativní) programy hlásí selhání prostřednictvím ukončovací kódy, které PowerShell sleduje odděleně od vlastního systému chyb.

Typy chyb

Neukončující chyby

Neukončující chyba hlásí problém, ale nezastaví kanál. Příkaz pokračuje ve zpracování následných vstupních objektů. Neukončující chyby se generují pomocí:

  • Cmdlet Write-Error
  • Metoda $PSCmdlet.WriteError() v pokročilých funkcích
  • Rutiny, u jednotlivých vstupních objektů dochází k obnovitelným chybám

PowerShell ve výchozím nastavení zobrazí chybovou zprávu a pokračuje v provádění.

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

V tomto příkladu Get-Content hlásí neukončující chybu a noSuchFile.txt pak pokračuje ve zpracování file3.txt.

Neukončující chyby se neaktivují nebo catch ve výchozím nastavení neaktivujítrap.

Chyby ukončující příkazy

Chyba ukončující příkaz zastaví spuštění aktuálního příkazu (kanálu), ale spuštění pokračuje na dalším příkazu ve skriptu. Chyby ukončující příkazy se generují pomocí:

  • Metoda $PSCmdlet.ThrowTerminatingError() v pokročilých funkcích a zkompilovaných rutinách
  • Chyby modulu, například CommandNotFoundException (volání příkazu, který neexistuje) a ParameterBindingException (neplatné argumenty parametrů)
  • Volání metody .NET, která vyvolává výjimky, například [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'

Chyby ukončující příkazy mohou být zachyceny try/catch a trap.

Poznámka:

.ThrowTerminatingError() nekonzultuje -ErrorAction parametr (s výjimkou Break hodnoty, která zadává ladicí program). $ErrorActionPreference Vztahuje se však na chyby ukončující příkazy prostřednictvím obslužné rutiny na úrovni příkazů modulu. Může například potlačit chybu ukončující příkaz, $ErrorActionPreference = 'SilentlyContinue' aby skript pokračoval v dalším příkazu. Parametr -ErrorAction to nemůže provést. Podrobnosti najdete v tématu $ErrorActionPreference asymetrie.

Chyby ukončující skripty

Chyba ukončující skript uvolní celý zásobník volání. Provádění se úplně zastaví, pokud se chyba nezachytí blokem nebo try/catch příkazemtrap. Chyby ukončující skripty se generují pomocí:

  • Klíčové slovo throw
  • Parsování chyb (chyby syntaxe, které brání kompilaci skriptu)
  • Neukončující chyby eskalované-ErrorAction Stop nebo $ErrorActionPreference = 'Stop' neukončující kontexty. Další informace naleznete v tématu Jak eskalace funguje.
  • Určitá selhání kritického modulu
# 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)'

Klíčové throw slovo ve výchozím nastavení generuje chybu ukončující skript. Však může $ErrorActionPreference potlačitthrow, pokud je nastavena SilentlyContinue nebo .Ignore Při volání pokročilé funkce pomocí -ErrorAction SilentlyContinueparametru se překládá na místní $ErrorActionPreference hodnotu oboru, takže také potlačuje throw uvnitř této funkce.

Poznámka:

I v $ErrorActionPreference = 'Ignore'případě , throw že je potlačeno, stále zaznamenává položku v $Error. Tato Ignore hodnota brání $Error záznamu pouze pro neukončující chyby.

Důležité

Termíny ukončování příkazů a ukončování skriptů popisují rozsah dopadu, nikoli závažnost chyby. Chyba ukončující příkaz zastaví jeden příkaz. Chyba ukončující skript zastaví celý skript a jeho volající. Oba mohou být zachyceny try/catch.

Chyby externího programu

Externí (nativní) programy se přímo neúčastní chybového systému PowerShellu. Hlásí selhání prostřednictvím nenulového ukončovacího kódu, který PowerShell ukládá do $LASTEXITCODE automatické proměnné.

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

Ve výchozím nastavení nenulový ukončovací kód z nativního programu:

  • Nastaví $? na $false
  • NevygenerujeErrorRecord$Error
  • Neaktivuje ani neaktivujecatchtrap

PowerShell 7.3 přidal experimentální proměnnou $PSNativeCommandUseErrorActionPreferencepředvoleb, která se stala stabilní funkcí ve verzi 7.4. Když nastavíte tuto proměnnou na $true, způsobí, že nenulový ukončovací kód vygeneruje neukončující chybu , jejíž zpráva uvádí konkrétní ukončovací kód (a NativeCommandExitException). Tato chyba respektuje $ErrorActionPreference, takže nastavení na Stop podporu chyby na chybu ukončující skript, který lze zachytit try/catchs .

Proměnné stavu chyby

PowerShell udržuje několik automatických proměnných, které odrážejí aktuální stav chyby.

$?

Obsahuje $true , jestli poslední operace proběhla úspěšně a $false jestli došlo k nějaké chybě (neukončující nebo ukončující). Pro nativní příkazy $? je nastavena na základě ukončovací kód: $true pro ukončovací kód 0, $false jinak.

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

$Error

Obsahuje ArrayList nejnovější záznamy o chybách s nejnovější chybou v indexu 0. Seznam obsahuje až $MaximumErrorCount položky (výchozí 256).

Všechny ukončující chyby se přidají do $Errorsouboru . U ukončování chyb potlačí zobrazení, Ignore ale stále zaznamenává chybu v $Error. Všechny neukončující chyby se přidají, $Error pokud -ErrorAction Ignore nejsou použity pro neukončující chyby, které brání zobrazení i nahrávání.

$LASTEXITCODE

Obsahuje ukončovací kód posledního nativního programu, který se spustil. Hodnota 0 konvenčně označuje úspěch. Jakákoli nenulová hodnota značí selhání. Tato proměnná není ovlivněna chybami rutin PowerShellu.

Řízení chování chyb

Společný -ErrorAction parametr

Společný -ErrorAction parametr přepíše $ErrorActionPreference jeden příkaz. Určuje, jak PowerShell reaguje na neukončující chyby z daného příkazu.

Hodnota Chování
Continue Zobrazení chyby a pokračování (výchozí)
SilentlyContinue Potlačit zobrazení, přidat do $Error, pokračovat
Ignore Potlačení zobrazení a nepřidávejte do $Error
Stop Eskalace k ukončovací chybě (viz Postup eskalace)
Inquire Výzva k zadání rozhodnutí uživatele
Break Zadejte ladicí program.

-ErrorAction nemění chování chyb generovaných funkcí $PSCmdlet.ThrowTerminatingError(). Tyto chyby jsou vždy ukončující příkazy bez ohledu na předvolbu volajícího.

Proměnná $ErrorActionPreference

Proměnná $ErrorActionPreference předvoleb se vztahuje na všechny příkazy v aktuálním oboru a podřízených oborech. Přijímá stejné hodnoty jako -ErrorAction.

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

Pokud -ErrorAction je zadán v příkazu, má přednost před $ErrorActionPreference tímto příkazem.

Jak eskalace funguje

Pokud -ErrorAction Stop nebo $ErrorActionPreference = 'Stop' je v platnosti, PowerShell převede neukončující chyby na ukončující chyby pomocí následujícího mechanismu:

  1. Rutina interně volá WriteError() , aby vygeneruje neukončující chybu.
  2. Modul zkontroluje efektivní ErrorAction předvolbu příkazu.
  3. Vzhledem k tomu, že předvolba je Stop, modul vytvoří ActionPreferenceStopException , který zabalí původní záznam chyby.
  4. Jsou-li zachyceny catch, původní informace o chybě jsou přístupné prostřednictvím $_.Exception.ErrorRecord.

Rozsah eskalované chyby závisí na kontextu:

  • V jiných než pokročilých skriptech, funkcích nebo blocích skriptu se nastavení $ErrorActionPreference = 'Stop' eskaluje na chybu ukončující skript . Chyba se rozšíří do zásobníku volání.
  • V pokročilých funkcích a blocích skriptů (těch s [CmdletBinding()]) zůstává chyba ukončující příkaz. Provádění pokračuje po volání na další příkaz.
  • Předání -ErrorAction Stop do pokročilé funkce má stejný účinek jako nastavení $ErrorActionPreference = 'Stop' uvnitř, protože -ErrorAction se překládá na místní $ErrorActionPreference hodnotu oboru.

Příklady eskalace

  • Jiné než pokročilé: ukončování skriptu (po) se netiskne.

    & {
        param()
        $ErrorActionPreference = 'Stop'
        1/0  # Divide by zero error
    } 2>$null
    'after'
    
  • ADVANCED: ukončování příkazů ('after' DO print)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'
        1/0  # Divide by zero error
    } 2>$null
    'after'
    
  • Bez -ErrorAction Stop: neukončování, catch se nespustí

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • S -ErrorAction Stop: eskalováno na ukončení

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

Eskalované chyby mohou být zachyceny jejich původním typem výjimky. Modul rozbalí ActionPreferenceStopException základní výjimku:

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

Asymetrie $ErrorActionPreference

Parametr -ErrorAction a $ErrorActionPreference proměnná se chovají jinak s ukončovacími chybami. Je důležité pochopit tuto asymetrii:

  • -ErrorAction má vliv pouze na neukončující chyby. Při volání $PSCmdlet.ThrowTerminatingError()-ErrorAction rutiny se parametr ignoruje (s výjimkou Break, který zadá ladicí program). Chyba se vždy vyvolá.

  • $ErrorActionPreference ovlivňuje neukončující i ukončovací chyby. Obslužná rutina chyby na úrovni příkazu modulu čte $ErrorActionPreference (nikoli -ErrorAction parametr) a může potlačit chybu ukončující příkaz, pokud je SilentlyContinue hodnota nebo 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'

Důležité

$ErrorActionPreference nemůže potlačit chyby, které jsou SuppressPromptInInterpreter nastavené na true. Tyto proměnné se vždy šíří bez ohledu na proměnnou předvoleb. Mezi příklady tohoto typu chyby patří:

  • ActionPreferenceStopException z -ErrorAction Stop eskalace
  • Chyby v metodách třídy PowerShellu
  • PipelineStoppedException

Řešte chyby

try/catch/finally

Slouží try/catch/finally ke zpracování chyb ukončování příkazů a ukončování skriptů. Pokud dojde k chybě uvnitř try bloku, PowerShell vyhledá odpovídající catch blok. Blok finally se vždy spustí bez ohledu na to, jestli došlo k chybě.

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
}

try Uvnitř bloku modul nastaví interní příznak, který způsobí neukončující chyby eskalované -ErrorAction Stop nebo $ErrorActionPreference = 'Stop' se rozšíří do catch bloku. Toto chování je navržené, ne zvláštní případ.

Úplné podrobnosti o syntaxi najdete v tématu about_Try_Catch_Finally.

trap

Příkaz trap zpracovává ukončovací chyby na úrovni oboru. Pokud dojde k chybě kdekoli v nadřazeném oboru, blok se trap spustí.

  • Výchozí (ne break nebo continue): Chyba se zobrazí a spuštění pokračuje v dalším příkazu za příkazem, který způsobil chybu.
  • continue in the trap: Suppresses the error message and resumes at the next statement.
  • break v soutisku: Chyba se rozšíří do nadřazeného oboru.
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'

Úplné podrobnosti o syntaxi najdete v tématu about_Trap.

Hlášení chyb ve funkcích a skriptech

Při psaní funkcí a skriptů zvolte mechanismus zasílání zpráv o chybách, který odpovídá závažnosti selhání.

Neukončující – použití Write-Error

Používá Write-Error se, když může funkce pokračovat ve zpracování jiného vstupu. To je vhodné pro funkce kanálu, které zpracovávají více objektů a dochází k chybám u jednotlivých položek.

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

Poznámka:

V pokročilých funkcích (těch, které [CmdletBinding()]mají) místo $PSCmdlet.WriteError()Write-Error toho, abyste měli jistotu, že $? je správně nastavená $false na rozsah volajícího. Rutina Write-Error není vždy správně nastavená $? .

Ukončování příkazů – use $PSCmdlet.ThrowTerminatingError()

Použijte $PSCmdlet.ThrowTerminatingError() , když funkce nemůže pokračovat vůbec, ale volající by se měl rozhodnout, jak se má selhání zpracovat. Toto je doporučený přístup v pokročilých funkcích.

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
}

Jakmile tato chyba funkci opustí, volající ji ve výchozím nastavení považuje za neukončující chybu. Volající ho může eskalovat s -ErrorAction Stop.

Ukončování skriptů – použití throw

Použijte throw , když obnovení není možné a celý skript by se měl zastavit.

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

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

Jaký mechanismus se má použít

  • Při zpracování více vstupů, kde některé mohou selhat, použít Write-Error nebo $PSCmdlet.WriteError().
  • Pokud funkce nemůže pokračovat, použijte $PSCmdlet.ThrowTerminatingError() a nechte volajícího rozhodnout, jak ji zpracovat.
  • Pokud se celý skript musí okamžitě zastavit, použijte throw.

Souhrn typů chyb

Následující tabulky shrnují vlastnosti a chování různých typů chyb v PowerShellu.

Neukončující chyba

Neukončující chyby mohou být generovány Write-Error nebo $PSCmdlet.WriteError().

Vlastnost Description
Rozsah dopadu Kanál pokračuje
Zachyceno catch Ne (pokud není eskalováno)
Zachyceno trap Ne (pokud není eskalováno)
Přidáno do $Error Ano (pokud Ignore)
Nastaví $? na $false Ano
Ovlivněno -ErrorAction Ano
Ovlivněno $ErrorActionPreference Ano

Chyba ukončení příkazu

Chyby ukončující příkazy mohou být generovány chybami ThrowTerminatingError()modulu, výjimkami metod .NET nebo -ErrorAction Stop v pokročilých kontextech.

Vlastnost Description
Rozsah dopadu Aktuální příkaz se zastaví; skript pokračuje
Zachyceno catch Ano
Zachyceno trap Ano
Přidáno do $Error Ano
Nastaví $? na $false Ano
Ovlivněno -ErrorAction Ne (Break pouze)
Ovlivněno $ErrorActionPreference Ano (může potlačit)

Chyba ukončování skriptu

Chyby ukončující skripty můžou být generovány throw, parsovat chyby nebo -ErrorAction Stop v nepokročilejších kontextech.

Vlastnost Description
Rozsah dopadu Odvíjení zásobníku volání
Zachyceno catch Ano
Zachyceno trap Ano
Přidáno do $Error Ano
Nastaví $? na $false Ano
Ovlivněno -ErrorAction Ne
Ovlivněno $ErrorActionPreference throw: Ano (může potlačit)
Ovlivněno $ErrorActionPreference Eskalace: závisí na kontextu.

Viz také