Partilhar via


about_Error_Handling

Breve descrição

Descreve os tipos de erros no PowerShell e os mecanismos para os tratar.

Descrição longa

O PowerShell distingue três categorias de erros:

  • Erros não terminantes
  • Erros de terminação de instruções
  • Erros de terminação de script

Compreender a distinção é essencial para escrever scripts e módulos fiáveis, porque cada categoria tem comportamentos padrão diferentes e requer técnicas de tratamento distintas.

Além disso, programas externos (nativos) reportam falhas através de códigos de saída, que o PowerShell monitoriza separadamente do seu próprio sistema de erros.

Tipos de erros

Erros não terminantes

Um erro de não terminação reporta um problema, mas não para o pipeline. O comando continua a processar os objetos de entrada subsequentes. Os erros não terminantes são gerados por:

  • O Write-Error cmdlet
  • O $PSCmdlet.WriteError() método em funções avançadas
  • Cmdlets que encontram falhas recuperáveis em objetos de entrada individuais

Por defeito, o PowerShell mostra a mensagem de erro e continua a execução.

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

Neste exemplo, Get-Content reporta um erro de não terminação para noSuchFile.txt e depois continua a processar file3.txt.

Erros de não terminação não são acionados catch nem trap por defeito.

Erros de terminação de instruções

Um erro de terminação de instrução impede que a instrução atual (pipeline) seja executada, mas a execução continua na próxima instrução do script. Erros de terminação de instrução são gerados por:

  • O $PSCmdlet.ThrowTerminatingError() método em funções avançadas e cmdlets compilados
  • Erros do motor como CommandNotFoundException (chamar um comando que não existe) e ParameterBindingException (argumentos de parâmetros inválidos)
  • .NET que lançam exceções, como [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'

Erros de terminação de instruções podem ser detetados por try/catch e trap.

Observação

.ThrowTerminatingError() não consulta o -ErrorAction parâmetro (exceto o Break valor, que entra no depurador). No entanto, $ErrorActionPreferenceaplica-se a erros de terminação de instruções através do handler ao nível da instrução do motor. Por exemplo, $ErrorActionPreference = 'SilentlyContinue' pode suprimir um erro de terminação de instrução para que o script continue na próxima instrução. O -ErrorAction parâmetro não consegue fazer isto. Para mais detalhes, veja A assimetria $ErrorActionPreference.

Erros de terminação de script

Um erro de terminação de script desenrola toda a pilha de chamadas. A execução para completamente, a menos que o erro seja detetado por um try/catch bloco ou trap sentença. Os erros de terminação de scripts são gerados por:

  • A palavra-chave throw
  • Erros de análise (erros de sintaxe que impedem a compilação do script)
  • Erros não terminantes escalados por -ErrorAction Stop ou $ErrorActionPreference = 'Stop' em contextos não avançados. Para mais informações, veja Como funciona a escalada.
  • Certas falhas críticas no motor
# 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)'

A throw palavra-chave gera um erro de terminação de script por defeito. No entanto, $ErrorActionPreferencepode suprimir throw quando definido como SilentlyContinue ou Ignore. Ao chamar uma função avançada com -ErrorAction SilentlyContinue, o parâmetro traduz-se num valor local $ErrorActionPreference no escopo, pelo que também suprime throw dentro dessa função.

Observação

Mesmo com $ErrorActionPreference = 'Ignore', um throw que está suprimido ainda regista uma entrada em $Error. O Ignore valor apenas impede $Error a gravação de erros que não terminam .

Importante

Os termos terminação de instrução e terminação de script descrevem o âmbito do impacto, não a gravidade do erro. Um erro de terminação de instrução para uma afirmação. Um erro de terminação de script para todo o script e os seus chamadores. Ambos podem ser capturados por try/catch.

Erros de programas externos

Programas externos (nativos) não participam diretamente no sistema de erros do PowerShell. Reportam a falha através de um código de saída diferente de zero, que o PowerShell armazena na $LASTEXITCODE variável automática.

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

Por defeito, um código de saída diferente de zero de um programa nativo:

  • Conjuntos $? para $false
  • Não gera um ErrorRecord em$Error
  • Não desencadeia catch outrap

O PowerShell 7.3 adicionou a variável $PSNativeCommandUseErrorActionPreferencede preferência experimental , que se tornou uma funcionalidade estável na 7.4. Quando define esta variável para $true, faz com que um código de saída não nulo emita um erro de não terminação cuja mensagem indica o código de saída específico (a NativeCommandExitException). Este erro respeita $ErrorActionPreference, pelo que defini-lo Stop para promove o erro para um erro de terminação de script que pode ser apanhado com/trycatch .

Variáveis de estado de erro

O PowerShell mantém várias variáveis automáticas que refletem o estado atual do erro.

$?

Contém $true se a última operação foi bem-sucedida e $false se produziu algum erro (não terminando ou terminando). Para comandos nativos, $? é definido com base no código de saída: $true para o código 0de saída , $false caso contrário.

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

$Error

E ArrayList que armazena os registos de erro mais recentes, com o erro mais recente no índice 0. A lista mantém-se até $MaximumErrorCount entradas (por defeito 256).

Todos os erros de terminação são adicionados a $Error. Para terminar erros, Ignore suprime a visualização mas ainda regista o erro em $Error. Todos os que não terminam são adicionados a $Error menos que -ErrorAction Ignore sejam usados em erros que não terminam, o que impede tanto a visualização como a gravação.

$LASTEXITCODE

Contém o código de saída do último programa nativo que foi executado. Um valor de 0 indica convencionalmente sucesso. Qualquer valor diferente de zero indica falha. Esta variável não é afetada por erros do cmdlet do PowerShell.

Comportamento de erro de controlo

O -ErrorAction parâmetro comum

O -ErrorAction parâmetro comum sobrepõe-se $ErrorActionPreference a um único comando. Controla como o PowerShell responde a erros que não terminam desse comando.

Value Comportamento
Continue Mostrar o erro e continuar (predefinido)
SilentlyContinue Suprimir exibição, adicionar a $Error, continuar
Ignore Suprimir o ecrã e não adicionar a $Error
Stop Escalar para um erro de terminação (ver Como funciona a escalonamento)
Inquire Incentive o utilizador a tomar uma decisão
Break Entra o depurador

-ErrorAction não altera o comportamento dos erros gerados por $PSCmdlet.ThrowTerminatingError(). Esses erros terminam sempre a instrução, independentemente da preferência do chamador.

A $ErrorActionPreference variável

A $ErrorActionPreference variável de preferência aplica-se a todos os comandos no âmbito atual e filho. Aceita os mesmos valores que -ErrorAction.

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

Quando -ErrorAction é especificado num comando, tem precedência sobre $ErrorActionPreference esse comando.

Como funciona a escalada

Quando -ErrorAction Stop ou $ErrorActionPreference = 'Stop' está em vigor, o PowerShell converte erros de não terminação em erros de terminação usando o seguinte mecanismo:

  1. Um cmdlet chama WriteError() internamente para emitir um erro de não terminação.
  2. O motor verifica a preferência efetiva ErrorAction pelo comando.
  3. Como a preferência é Stop, o motor cria um ActionPreferenceStopException que envolve o registo de erro original.
  4. Se capturado por catch, a informação original de erro é acessível através de $_.Exception.ErrorRecord.

O âmbito do erro escalado depende do contexto:

  • Em scripts, funções ou blocos de script não avançados , a definição $ErrorActionPreference = 'Stop' escala para um erro que termina o script . O erro propaga-se pela pilha de chamadas.
  • Em funções avançadas e blocos de script (aqueles com [CmdletBinding()]), o erro mantém-se a terminar a instrução. A execução continua na declaração seguinte após a chamada.
  • Passar -ErrorAction Stop para uma função avançada tem o mesmo efeito que definir $ErrorActionPreference = 'Stop' dentro dela, porque -ErrorAction se traduz num valor local $ErrorActionPreference no escopo.

Exemplos de escalada

  • NÃO avançado: terminação de script ('after' NÃO imprime)

    & {
        param()
        $ErrorActionPreference = 'Stop'
        Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • ADVANCED: terminação de instrução ('after' DOES print)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • Sem -ErrorAction Stop: não terminando, a captura não corre

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Com -ErrorAction Stop: escalou para terminar

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

Erros escalonados podem ser detetados pelo seu tipo de exceção original. O motor desdobra o ActionPreferenceStopException para encontrar a exceção subjacente:

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

A $ErrorActionPreference assimetria

O -ErrorAction parâmetro e a $ErrorActionPreference variável comportam-se de forma diferente com erros de terminação. É importante compreender esta assimetria:

  • -ErrorAction Só afeta erros que não terminam . Quando um cmdlet chama $PSCmdlet.ThrowTerminatingError(), o -ErrorAction parâmetro é ignorado (exceto , Breakque entra no depurador). O erro é sempre lançado.

  • $ErrorActionPreference afeta tanto erros de não terminação como de terminação de sentença. O manipulador de erro ao nível da instrução do motor lê $ErrorActionPreference (não o -ErrorAction parâmetro) e pode suprimir um erro de terminação de instruções quando o valor é SilentlyContinue ou 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 não é possível suprimir erros que tenham SuppressPromptInInterpreter definido para true. Estas propagam-se sempre independentemente da variável de preferência. Exemplos deste tipo de erro incluem:

  • ActionPreferenceStopException A partir da -ErrorAction Stop escalada
  • Erros dentro dos métodos de classe PowerShell
  • PipelineStoppedException

Lidar com erros

try/catch/finally

Use try/catch/finally para lidar com erros de terminação de instruções e de terminação de scripts. Quando ocorre um erro dentro de um try bloco, o PowerShell procura um bloco correspondente catch . O finally bloco corre sempre, independentemente de ter ocorrido ou não um erro.

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
}

Dentro de um try bloco, o motor define uma bandeira interna que provoca erros de não terminação escalados por -ErrorAction Stop ou $ErrorActionPreference = 'Stop' que se propagam para o bloco catch . Isto é um comportamento desenhado, não um caso especial.

Para detalhes completos da sintaxe, veja about_Try_Catch_Finally.

trap

A trap instrução trata de erros de terminação ao nível do âmbito. Quando ocorre um erro em qualquer parte do âmbito de encerramento, o trap bloco executa-se.

  • Default (não break ou continue): O erro é exibido e a execução continua na próxima instrução após aquela que causou o erro.
  • continue na armadilha: Suprime a mensagem de erro e retoma na próxima instrução.
  • break na armadilha: O erro propaga-se para o âmbito pai.
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'

Para detalhes completos da sintaxe, veja about_Trap.

Relatórios de erros em funções e scripts

Ao escrever funções e scripts, escolha o mecanismo de reporte de erros que corresponda à gravidade da falha.

Não-terminação - utilização Write-Error

Use Write-Error quando a função puder continuar a processar outros inputs. Isto é apropriado para funções de pipeline que processam múltiplos objetos e enfrentam falhas em itens individuais.

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

Observação

Em funções avançadas (aquelas com [CmdletBinding()]), use $PSCmdlet.WriteError() em vez de Write-Error para garantir que $? está corretamente definido como $false no âmbito do chamador. O Write-Error cmdlet nem sempre se ajusta $? corretamente.

Terminação de instruções - utilização $PSCmdlet.ThrowTerminatingError()

$PSCmdlet.ThrowTerminatingError() Use quando a função não puder continuar de todo, mas o chamador deve decidir como lidar com a falha. Esta é a abordagem recomendada em funções avançadas.

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
}

Depois de o erro sair da função, o chamador trata-o como um erro não terminante por defeito. O interlocutor pode escalar a situação com -ErrorAction Stop.

Terminação de scripts - utilização throw

Usa throw quando a recuperação não for possível e o script inteiro deve parar.

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

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

Que mecanismo usar

  • Ao processar múltiplas entradas onde algumas podem falhar, use Write-Error ou $PSCmdlet.WriteError().
  • Se a função não puder continuar, use $PSCmdlet.ThrowTerminatingError() e deixe que o interlocutor decida como a gerir.
  • Se o script inteiro tiver de parar imediatamente, use throw.

Resumo dos tipos de erro

As tabelas seguintes resumem as propriedades e comportamentos dos diferentes tipos de erro no PowerShell.

Erro de não terminação

Erros não terminantes podem ser gerados por Write-Error ou $PSCmdlet.WriteError().

Attribute Descrição
Dimensão do impacto O oleoduto continua
Apanhado por catch Não (a não ser que seja escalado)
Apanhado por trap Não (a não ser que seja escalado)
Acrescentado a $Error Sim (a menos que Ignore)
Conjuntos $? para $false Sim
Afetado por -ErrorAction Sim
Afetado por $ErrorActionPreference Sim

Erro de terminação de instruções

Erros de terminação de instruções podem ser gerados por ThrowTerminatingError(), erros do motor, exceções do método .NET ou -ErrorAction Stop em contextos avançados.

Attribute Descrição
Dimensão do impacto A declaração atual para; O guião continua
Apanhado por catch Sim
Apanhado por trap Sim
Acrescentado a $Error Sim
Conjuntos $? para $false Sim
Afetado por -ErrorAction Não (Break apenas)
Afetado por $ErrorActionPreference Sim (pode suprimir)

Erro de terminação de script

Erros de terminação de script podem ser gerados por throw, erros de análise ou -ErrorAction Stop em contextos não avançados.

Attribute Descrição
Dimensão do impacto Desenrolar a pilha de chamadas
Apanhado por catch Sim
Apanhado por trap Sim
Acrescentado a $Error Sim
Conjuntos $? para $false Sim
Afetado por -ErrorAction No
Afetado por $ErrorActionPreference throw: Sim (pode suprimir)
Afetado por $ErrorActionPreference Escalado: depende do contexto

Consulte também