Condividi tramite


about_Error_Handling

Descrizione breve

Descrive i tipi di errori in PowerShell e i meccanismi per gestirli.

Descrizione lunga

PowerShell distingue tre categorie di errori:

  • Errori non irreversibili
  • Errori di terminazione delle istruzioni
  • Errori di terminazione dello script

La comprensione della distinzione è essenziale per la scrittura di moduli e script affidabili, perché ogni categoria ha un comportamento predefinito diverso e richiede tecniche di gestione diverse.

Inoltre, i programmi esterni (nativi) segnalano errori tramite codici di uscita, che PowerShell tiene traccia separatamente dal proprio sistema di errore.

Tipi di errori

Errori non irreversibili

Un errore non irreversibile segnala un problema ma non arresta la pipeline. Il comando continua a elaborare gli oggetti di input successivi. Gli errori non irreversibili vengono generati da:

  • Cmdlet Write-Error
  • Metodo $PSCmdlet.WriteError() nelle funzioni avanzate
  • Cmdlet che riscontrano errori ripristinabili nei singoli oggetti di input

Per impostazione predefinita, PowerShell visualizza il messaggio di errore e continua l'esecuzione.

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

In questo esempio viene Get-Content segnalato un errore non irreversibile per noSuchFile.txt e quindi continua l'elaborazione file3.txtdi .

Gli errori non irreversibili non vengono attivati catch o trap per impostazione predefinita.

Errori di terminazione delle istruzioni

Un errore di terminazione dell'istruzione interrompe l'esecuzione dell'istruzione corrente (pipeline), ma l'esecuzione continua con l'istruzione successiva nello script. Gli errori di terminazione delle istruzioni vengono generati da:

  • Metodo $PSCmdlet.ThrowTerminatingError() nelle funzioni avanzate e nei cmdlet compilati
  • Errori del motore, ad CommandNotFoundException esempio (chiamata di un comando che non esiste) e ParameterBindingException (argomenti di parametro non validi)
  • Chiamate al metodo .NET che generano eccezioni, ad esempio [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'

Gli errori di terminazione delle istruzioni possono essere rilevati da try/catch e trap.

Annotazioni

.ThrowTerminatingError() non consulta il -ErrorAction parametro ( ad eccezione del Break valore , che immette il debugger). Tuttavia, $ErrorActionPreferencesi applica agli errori di terminazione delle istruzioni tramite il gestore a livello di istruzione del motore. Ad esempio, $ErrorActionPreference = 'SilentlyContinue' può eliminare un errore di terminazione dell'istruzione in modo che lo script continui all'istruzione successiva. Il -ErrorAction parametro non può eseguire questa operazione. Per informazioni dettagliate, vedere l'$ErrorActionPreference asimmetria.

Errori di terminazione dello script

Un errore di terminazione dello script rimuove l'intero stack di chiamate. L'esecuzione viene arrestata completamente a meno che l'errore non venga intercettato da un try/catch blocco o trap un'istruzione . Gli errori di terminazione dello script vengono generati da:

  • Parola chiave throw
  • Errori di analisi (errori di sintassi che impediscono la compilazione dello script)
  • Errori non irreversibili inoltrati da -ErrorAction Stop o $ErrorActionPreference = 'Stop' in contesti non avanzati. Per altre informazioni, vedere Funzionamento dell'escalation.
  • Alcuni errori critici del motore
# 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)'

La throw parola chiave genera un errore di terminazione dello script per impostazione predefinita. Tuttavia, $ErrorActionPreferencepuò eliminare throw se impostato su SilentlyContinue o Ignore. Quando si chiama una funzione avanzata con -ErrorAction SilentlyContinue, il parametro si traduce in un valore locale $ErrorActionPreference dell'ambito, quindi elimina throw anche all'interno di tale funzione.

Annotazioni

Anche con $ErrorActionPreference = 'Ignore', un throw oggetto eliminato registra ancora una voce in $Error. Il Ignore valore impedisce solo la registrazione per errori non irreversibili$Error.

Importante

I termini statement-terminating e script-terminating descrivono l'ambito di impatto, non la gravità dell'errore. Un errore di terminazione dell'istruzione arresta un'istruzione. Un errore di terminazione dello script arresta l'intero script e i relativi chiamanti. Entrambi possono essere intercettati da try/catch.

Errori del programma esterno

I programmi esterni (nativi) non partecipano direttamente al sistema di errori di PowerShell. Segnalano un errore tramite un codice di uscita diverso da zero, che PowerShell archivia nella $LASTEXITCODE variabile automatica.

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

Per impostazione predefinita, un codice di uscita diverso da zero da un programma nativo:

  • Imposta su $?$false
  • Non genera un in ErrorRecord$Error
  • Non attivacatch otrap

PowerShell 7.3 ha aggiunto la variabile di preferenza sperimentale $PSNativeCommandUseErrorActionPreference, che è diventata una funzionalità stabile nella versione 7.4. Quando si imposta questa variabile su $true, genera un codice di uscita diverso da zero per generare un errore non irreversibile il cui messaggio indica il codice di uscita specifico (a NativeCommandExitException). Questo errore rispetta $ErrorActionPreference, quindi impostandolo per Stop promuovere l'errore a un errore di terminazione dello script che può essere intercettato con/trycatch .

Variabili di stato degli errori

PowerShell gestisce diverse variabili automatiche che riflettono lo stato di errore corrente.

$?

Contiene $true se l'ultima operazione ha avuto esito positivo e $false se ha generato un errore (senza terminazione o terminazione). Per i comandi nativi, $? è impostato in base al codice di uscita: $true per il codice 0di uscita , $false in caso contrario.

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

$Error

Oggetto ArrayList che archivia i record di errore più recenti, con l'errore più recente in corrispondenza dell'indice 0. L'elenco contiene fino a $MaximumErrorCount voci (impostazione predefinita 256).

Tutti gli errori di terminazione vengono aggiunti a $Error. Per gli errori di terminazione, Ignore elimina la visualizzazione ma registra comunque l'errore in $Error. Tutti i non terminanti vengono aggiunti a $Error , a meno che non -ErrorAction Ignore vengano utilizzati in errori non irreversibili, che impediscono sia la visualizzazione che la registrazione.

$LASTEXITCODE

Contiene il codice di uscita dell'ultimo programma nativo eseguito. Un valore convenzionalmente 0 indica l'esito positivo. Qualsiasi valore diverso da zero indica un errore. Questa variabile non è interessata dagli errori del cmdlet di PowerShell.

Controllare il comportamento degli errori

Parametro -ErrorAction comune

Il parametro comune esegue l'override -ErrorAction$ErrorActionPreference di un singolo comando. Controlla in che modo PowerShell risponde a errori non irreversibili da tale comando.

Valore Comportamento
Continue Visualizzare l'errore e continuare (impostazione predefinita)
SilentlyContinue Eliminare la visualizzazione, aggiungere a $Error, continuare
Ignore Elimina la visualizzazione e non aggiungi a $Error
Stop Eseguire l'escalation a un errore irreversibile (vedere Funzionamento dell'escalation)
Inquire Richiedere all'utente una decisione
Break Immettere il debugger

-ErrorAction non modifica il comportamento degli errori generati da $PSCmdlet.ThrowTerminatingError(). Tali errori vengono sempre terminati con istruzioni indipendentemente dalla preferenza del chiamante.

Variabile $ErrorActionPreference

La $ErrorActionPreference variabile di preferenza si applica a tutti i comandi nell'ambito corrente e negli ambiti figlio. Accetta gli stessi valori di -ErrorAction.

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

Quando -ErrorAction viene specificato in un comando, ha la precedenza $ErrorActionPreference su tale comando.

Funzionamento dell'escalation

Quando -ErrorAction Stop o $ErrorActionPreference = 'Stop' è attivo, PowerShell converte gli errori non irreversibili in errori irreversibili usando il meccanismo seguente:

  1. Un cmdlet chiama WriteError() internamente per generare un errore non irreversibile.
  2. Il motore controlla la preferenza effettiva ErrorAction per il comando.
  3. Poiché la preferenza è Stop, il motore crea un oggetto ActionPreferenceStopException che esegue il wrapping del record di errore originale.
  4. Se rilevata da catch, le informazioni di errore originali sono accessibili tramite $_.Exception.ErrorRecord.

L'ambito dell'errore inoltrato dipende dal contesto:

  • In script, funzioni o blocchi di script non avanzati , l'impostazione $ErrorActionPreference = 'Stop' esegue l'escalation a un errore di terminazione dello script . L'errore propaga lo stack di chiamate.
  • Nelle funzioni avanzate e nei blocchi di script (quelli con [CmdletBinding()]), l'errore rimane in fase di terminazione. L'esecuzione continua all'istruzione successiva dopo la chiamata.
  • Il passaggio -ErrorAction Stop a una funzione avanzata ha lo stesso effetto dell'impostazione $ErrorActionPreference = 'Stop' al suo interno, perché -ErrorAction si traduce in un valore locale $ErrorActionPreference dell'ambito.

Esempi di escalation

  • NON avanzato: terminazione dello script ('after' non stampa)

    & {
        param()
        $ErrorActionPreference = 'Stop'
        Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • ADVANCED: terminazione dell'istruzione ('after' DOES print)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • Senza -ErrorAction Stop: non terminazione, catch non viene eseguito

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Con -ErrorAction Stop: è stato inoltrato alla terminazione

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

Gli errori inoltrati possono essere rilevati dal tipo di eccezione originale. Il motore annulla il wrapping di ActionPreferenceStopException per trovare l'eccezione sottostante:

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

Asymmetry $ErrorActionPreference

Il -ErrorAction parametro e la $ErrorActionPreference variabile si comportano in modo diverso con errori di terminazione. È importante comprendere questi dati asimmetria:

  • -ErrorAction influisce solo sugli errori non irreversibili . Quando un cmdlet chiama $PSCmdlet.ThrowTerminatingError(), il -ErrorAction parametro viene ignorato (ad eccezione di Break, che immette il debugger). L'errore viene sempre generato.

  • $ErrorActionPreference influisce sugli errori non irreversibili e di terminazione delle istruzioni. Il gestore degli errori a livello di istruzione del motore legge $ErrorActionPreference (non il -ErrorAction parametro) e può eliminare un errore di terminazione dell'istruzione quando il valore è SilentlyContinue o 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'

Importante

$ErrorActionPreference non può eliminare gli errori SuppressPromptInInterpreter impostati su true. Questi vengono sempre propagati indipendentemente dalla variabile di preferenza. Alcuni esempi di questo tipo di errore includono:

  • ActionPreferenceStopExceptiondall'escalation -ErrorAction Stop
  • Errori all'interno dei metodi della classe PowerShell
  • PipelineStoppedException

Gestire gli errori

try/catch/finally

Usare try/catch/finally per gestire gli errori di terminazione delle istruzioni e di terminazione dello script. Quando si verifica un errore all'interno di un try blocco, PowerShell cerca un blocco corrispondente catch . Il finally blocco viene sempre eseguito, indipendentemente dal fatto che si sia verificato o meno un errore.

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
}

All'interno di un try blocco, il motore imposta un flag interno che causa l'escalation di errori non irreversibili da -ErrorAction Stop o $ErrorActionPreference = 'Stop' la propagazione al catch blocco. Questo comportamento è progettato, non un caso speciale.

Per informazioni dettagliate sulla sintassi, vedere about_Try_Catch_Finally.

trap

L'istruzione trap gestisce gli errori di terminazione a livello di ambito. Quando si verifica un errore in qualsiasi punto dell'ambito di inclusione, il trap blocco viene eseguito.

  • Valore predefinito (no break o continue): l'errore viene visualizzato e l'esecuzione continua all'istruzione successiva dopo quella che ha causato l'errore.
  • continue nella trap: elimina il messaggio di errore e riprende all'istruzione successiva.
  • break nella trap: l'errore si propaga all'ambito padre.
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'

Per informazioni dettagliate sulla sintassi, vedere about_Trap.

Segnalazione di errori in funzioni e script

Quando si scrivono funzioni e script, scegliere il meccanismo di segnalazione degli errori che corrisponde alla gravità dell'errore.

Non terminazione - uso Write-Error

Usare Write-Error quando la funzione può continuare a elaborare altri input. Questa opzione è appropriata per le funzioni della pipeline che elaborano più oggetti e riscontrano errori nei singoli elementi.

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

Annotazioni

Nelle funzioni avanzate (quelle con [CmdletBinding()]), usare $PSCmdlet.WriteError() invece di Write-Error per assicurarsi che $? sia impostato correttamente su $false nell'ambito del chiamante. Il Write-Error cmdlet non viene sempre impostato $? correttamente.

Statement-terminating - use $PSCmdlet.ThrowTerminatingError()

Usare $PSCmdlet.ThrowTerminatingError() quando la funzione non può continuare, ma il chiamante deve decidere come gestire l'errore. Questo è l'approccio consigliato nelle funzioni avanzate.

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
}

Dopo che l'errore lascia la funzione, il chiamante lo considera come un errore non irreversibile per impostazione predefinita. Il chiamante può inoltrarlo con -ErrorAction Stop.

Terminazione dello script- uso throw

Usare throw quando il ripristino non è possibile e l'intero script deve essere arrestato.

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

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

Quale meccanismo usare

  • Quando si elaborano più input in cui alcuni potrebbero non riuscire, usare Write-Error o $PSCmdlet.WriteError().
  • Se la funzione non può continuare, usare $PSCmdlet.ThrowTerminatingError() e consentire al chiamante di decidere come gestirla.
  • Se l'intero script deve essere arrestato immediatamente, usare throw.

Riepilogo dei tipi di errore

Le tabelle seguenti riepilogano le proprietà e i comportamenti dei diversi tipi di errore in PowerShell.

Errore non irreversibile

Gli errori non irreversibili possono essere generati da Write-Error o $PSCmdlet.WriteError().

Attribute Descrizione
Ambito dell'impatto La pipeline continua
Catturato da catch No (a meno che non venga inoltrata)
Catturato da trap No (a meno che non venga inoltrata)
Aggiunta a $Error Sì (a meno che Ignore)
Imposta su $?$false
Interessato da -ErrorAction
Interessato da $ErrorActionPreference

Errore di terminazione dell'istruzione

Gli errori di terminazione delle istruzioni possono essere generati da ThrowTerminatingError()errori del motore, eccezioni del metodo .NET o -ErrorAction Stop in contesti avanzati.

Attribute Descrizione
Ambito dell'impatto L'istruzione corrente si arresta; script continua
Catturato da catch
Catturato da trap
Aggiunta a $Error
Imposta su $?$false
Interessato da -ErrorAction No (Break solo)
Interessato da $ErrorActionPreference Sì (può eliminare)

Errore di terminazione dello script

Gli errori di terminazione dello script possono essere generati da throw, analizzare gli errori o -ErrorAction Stop in contesti non avanzati.

Attribute Descrizione
Ambito dell'impatto Rimozione dello stack di chiamate
Catturato da catch
Catturato da trap
Aggiunta a $Error
Imposta su $?$false
Interessato da -ErrorAction No
Interessato da $ErrorActionPreference throw: Sì (può eliminare)
Interessato da $ErrorActionPreference Escalation: dipende dal contesto

Vedere anche