about_Error_Handling

Descripción breve

Describe los tipos de errores en PowerShell y los mecanismos para controlarlos.

Descripción larga

PowerShell distingue tres categorías de errores:

  • Errores de no terminación
  • Errores de terminación de instrucciones
  • Errores de terminación de script

Comprender la distinción es esencial para escribir scripts y módulos confiables, ya que cada categoría tiene un comportamiento predeterminado diferente y requiere diferentes técnicas de control.

Además, los programas externos (nativos) notifican errores a través de códigos de salida, que PowerShell realiza un seguimiento por separado de su propio sistema de errores.

Tipos de errores

Errores de no terminación

Un error de no terminación notifica un problema, pero no detiene la canalización. El comando continúa procesando los objetos de entrada posteriores. Los errores de no terminación se generan mediante:

  • El Write-Error cmdlet
  • Método $PSCmdlet.WriteError() en funciones avanzadas
  • Cmdlets que encuentran errores recuperables en objetos de entrada individuales

De forma predeterminada, PowerShell muestra el mensaje de error y continúa la ejecución.

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

En este ejemplo, notifica un error de no terminación para noSuchFile.txt y, a continuación, Get-Content continúa procesando file3.txt.

Los errores de no terminación no se desencadenan catch o trap de forma predeterminada.

Errores de terminación de instrucciones

Un error de terminación de instrucción impide que se ejecute la instrucción actual (canalización), pero la ejecución continúa en la siguiente instrucción del script. Los errores de terminación de instrucciones se generan mediante:

  • Método $PSCmdlet.ThrowTerminatingError() en funciones avanzadas y cmdlets compilados
  • Errores de motor, como CommandNotFoundException (llamar a un comando que no existe) y ParameterBindingException (argumentos de parámetro no válidos)
  • Llamadas al método .NET que producen excepciones, 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'

Los errores de terminación de instrucciones se pueden detectar mediante try/catch y trap.

Nota:

.ThrowTerminatingError() no consulta el -ErrorAction parámetro (excepto el Break valor , que especifica el depurador). Sin embargo, $ErrorActionPreferencese aplica a los errores de terminación de instrucciones a través del controlador de nivel de instrucción del motor. Por ejemplo, $ErrorActionPreference = 'SilentlyContinue' puede suprimir un error de terminación de instrucción para que el script continúe en la instrucción siguiente. El -ErrorAction parámetro no puede hacerlo. Para obtener más información, consulte La $ErrorActionPreference asimetría.

Errores de terminación de script

Un error de terminación de script desenreda toda la pila de llamadas. La ejecución se detiene completamente a menos que una try/catch instrucción o trap bloque detecte el error. Los errores de terminación de script se generan mediante:

  • La palabra clave throw.
  • Análisis de errores (errores de sintaxis que impiden que el script se compile)
  • Errores de no terminación escalados por -ErrorAction Stop o $ErrorActionPreference = 'Stop' en contextos no avanzados. Para obtener más información, consulte Funcionamiento de la escalación.
  • Ciertos errores críticos del 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)'

La throw palabra clave genera un error de terminación de script de forma predeterminada. Sin embargo, $ErrorActionPreferencepuede suprimirse throw cuando se establece en SilentlyContinue o Ignore. Al llamar a una función avanzada con -ErrorAction SilentlyContinue, el parámetro se traduce en un valor local $ErrorActionPreference de ámbito, por lo que también suprime throw dentro de esa función.

Nota:

Incluso con $ErrorActionPreference = 'Ignore', un throw objeto que se suprime todavía registra una entrada en $Error. El Ignore valor solo impide $Error la grabación de errores de no terminación .

Importante

Los términos de terminación de instrucciones y terminación de script describen el ámbito del impacto, no la gravedad del error. Un error de terminación de instrucción detiene una instrucción. Un error de terminación de script detiene todo el script y sus autores de llamada. Ambos pueden ser capturados por try/catch.

Errores de programa externo

Los programas externos (nativos) no participan directamente en el sistema de errores de PowerShell. Notifican un error a través de un código de salida distinto de cero, que PowerShell almacena en la $LASTEXITCODE variable automática.

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

De forma predeterminada, un código de salida distinto de cero de un programa nativo:

  • Establece en $?$false
  • No genera un ErrorRecord en$Error
  • No desencadenacatch nitrap

PowerShell 7.3 agregó la variable $PSNativeCommandUseErrorActionPreferencede preferencia experimental , que se convirtió en una característica estable en la versión 7.4. Cuando establece esta variable $trueen , hace que un código de salida distinto de cero emita un error de no terminación cuyo mensaje indique el código de salida específico (a NativeCommandExitException). Este error respeta $ErrorActionPreference, por lo que establecerlo para Stop promover el error a un error de terminación de script que se puede detectar con/trycatch .

Variables de estado de error

PowerShell mantiene varias variables automáticas que reflejan el estado de error actual.

$?

Contiene $true si la última operación se realizó correctamente y $false si produjo algún error (sin terminación o terminación). En el caso de los comandos nativos, $? se establece en función del código de salida: $true para el código 0de salida ; $false de lo contrario, .

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

$Error

que ArrayList almacena los registros de error más recientes, con el error más reciente en el índice 0. La lista contiene hasta $MaximumErrorCount entradas (valor predeterminado 256).

Todos los errores de terminación se agregan a $Error. Para finalizar los errores, Ignore suprime la presentación, pero sigue registrando el error en $Error. Todas las operaciones de no terminación se agregan a $Error a menos -ErrorAction Ignore que se usen en errores de no terminación, lo que impide la visualización y la grabación.

$LASTEXITCODE

Contiene el código de salida del último programa nativo que se ejecutó. Un valor de 0 convencionalmente indica que se ha realizado correctamente. Cualquier valor distinto de cero indica un error. Esta variable no se ve afectada por errores de cmdlet de PowerShell.

Control del comportamiento del error

Parámetro -ErrorAction común

El -ErrorAction parámetro común invalida $ErrorActionPreference para un solo comando. Controla cómo Responde PowerShell a errores de no terminación desde ese comando.

Importancia Comportamiento
Continue Mostrar el error y continuar (valor predeterminado)
SilentlyContinue Suprimir la visualización, agregar a $Error, continuar
Ignore Suprimir la visualización y no agregar a $Error
Stop Escalado a un error de terminación (consulte Funcionamiento de la escalación)
Inquire Pedir al usuario una decisión
Break Escriba el depurador.

-ErrorAction no cambia el comportamiento de los errores generados por $PSCmdlet.ThrowTerminatingError(). Esos errores siempre son terminación de instrucciones independientemente de la preferencia del autor de la llamada.

Variable $ErrorActionPreference

La $ErrorActionPreference variable de preferencia se aplica a todos los comandos del ámbito actual y los ámbitos secundarios. Acepta los mismos valores que -ErrorAction.

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

Cuando -ErrorAction se especifica en un comando, tiene prioridad sobre $ErrorActionPreference ese comando.

Funcionamiento de la escalación

Cuando -ErrorAction Stop o $ErrorActionPreference = 'Stop' está en vigor, PowerShell convierte los errores de no terminación en errores de terminación mediante el siguiente mecanismo:

  1. Un cmdlet llama WriteError() internamente para emitir un error de no terminación.
  2. El motor comprueba la preferencia efectiva ErrorAction del comando.
  3. Dado que la preferencia es Stop, el motor crea un ActionPreferenceStopException que encapsula el registro de error original.
  4. Si se detecta mediante catch, se puede acceder a la información de error original a través de $_.Exception.ErrorRecord.

El ámbito del error escalado depende del contexto:

  • En scripts, funciones o bloques de scripts no avanzados , la configuración $ErrorActionPreference = 'Stop' se escala a un error de terminación de script . El error propaga la pila de llamadas.
  • En funciones avanzadas y bloques de script (aquellos con [CmdletBinding()]), el error permanece terminado por instrucciones. La ejecución continúa en la siguiente instrucción después de la llamada.
  • Pasar -ErrorAction Stop a una función avanzada tiene el mismo efecto que establecer $ErrorActionPreference = 'Stop' dentro de ella, ya que -ErrorAction se traduce en un valor local $ErrorActionPreference de ámbito.

Ejemplos de escalado

  • NO avanzado: terminación de script ('after' no imprime)

    & {
        param()
        $ErrorActionPreference = 'Stop'
        Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • ADVANCED: terminación de instrucciones ('after' DOES print)

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • Sin -ErrorAction Stop: sin terminación, catch no se ejecuta

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Con -ErrorAction Stop: escalado a terminación

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

El tipo de excepción original puede detectar errores escalados. El motor desencapsula para ActionPreferenceStopException buscar la excepción subyacente:

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

La $ErrorActionPreference asimetría

El -ErrorAction parámetro y la $ErrorActionPreference variable se comportan de forma diferente con errores de terminación. Es importante comprender esta asimetría:

  • -ErrorAction solo afecta a los errores de no terminación . Cuando un cmdlet llama a $PSCmdlet.ThrowTerminatingError(), se omite el -ErrorAction parámetro (excepto para Break, que entra en el depurador). El error siempre se produce.

  • $ErrorActionPreference afecta tanto a errores de no terminación como de terminación de instrucciones. El controlador de errores de nivel de instrucción del motor lee $ErrorActionPreference (no el -ErrorAction parámetro) y puede suprimir un error de terminación de instrucción cuando el valor es 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 no puede suprimir los errores que se han SuppressPromptInInterpreter establecido en true. Siempre se propagan independientemente de la variable de preferencia. Entre los ejemplos de este tipo de error se incluyen:

  • ActionPreferenceStopException desde la -ErrorAction Stop escalación
  • Errores dentro de los métodos de clase de PowerShell
  • PipelineStoppedException

Manejo de errores

try/catch/finally

Use try/catch/finally para controlar los errores de terminación de instrucciones y de terminación de scripts. Cuando se produce un error dentro de un try bloque, PowerShell busca un bloque coincidente catch . El finally bloque siempre se ejecuta, independientemente de si se produjo o no un error.

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 un try bloque, el motor establece una marca interna que provoca errores de no terminación escalados por -ErrorAction Stop o $ErrorActionPreference = 'Stop' para propagarse al catch bloque. Este comportamiento está diseñado, no un caso especial.

Para obtener información completa sobre la sintaxis, consulte about_Try_Catch_Finally.

trap

La trap instrucción controla los errores de terminación en el nivel de ámbito. Cuando se produce un error en cualquier parte del ámbito envolvente, el trap bloque se ejecuta.

  • Valor predeterminado (no break o continue): el error se muestra y la ejecución continúa en la siguiente instrucción después de la que provocó el error.
  • continue en la captura: suprime el mensaje de error y se reanuda en la siguiente instrucción.
  • break en la captura: el error se propaga al ámbito primario.
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 obtener información completa sobre la sintaxis, consulte about_Trap.

Notificación de errores en funciones y scripts

Al escribir funciones y scripts, elija el mecanismo de informes de errores que coincida con la gravedad del error.

Sin terminación: use Write-Error

Use Write-Error cuando la función pueda continuar procesando otra entrada. Esto es adecuado para las funciones de canalización que procesan varios objetos y detectan errores en elementos individuales.

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

Nota:

En funciones avanzadas (aquellas con [CmdletBinding()]), use $PSCmdlet.WriteError() en lugar de para asegurarse de Write-Error que $? está correctamente establecido $false en en el ámbito del autor de la llamada. El Write-Error cmdlet no siempre se establece $? correctamente.

Terminación de instrucciones: uso $PSCmdlet.ThrowTerminatingError()

Use $PSCmdlet.ThrowTerminatingError() cuando la función no pueda continuar en absoluto, pero el autor de la llamada debe decidir cómo controlar el error. Este es el enfoque recomendado en funciones avanzadas.

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
}

Una vez que el error deja la función, el autor de la llamada la trata como un error de no terminación de forma predeterminada. El autor de la llamada puede escalarlo con -ErrorAction Stop.

Terminación de script: uso throw

Use throw cuando la recuperación no sea posible y el script completo debe detenerse.

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

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

Mecanismo que se va a usar

  • Al procesar varias entradas en las que algunos pueden producir errores, use Write-Error o $PSCmdlet.WriteError().
  • Si la función no puede continuar, use $PSCmdlet.ThrowTerminatingError() y deje que el autor de la llamada decida cómo controlarla.
  • Si todo el script debe detenerse inmediatamente, use throw.

Resumen de los tipos de error

En las tablas siguientes se resumen las propiedades y comportamientos de los distintos tipos de error en PowerShell.

Error de no terminación

Los errores de no terminación se pueden generar mediante Write-Error o $PSCmdlet.WriteError().

Atributo Descripción
Ámbito de impacto Continúa la canalización
Atrapado por catch No (a menos que se escale)
Atrapado por trap No (a menos que se escale)
Agregado a $Error Sí (a menos Ignoreque )
Establece en $?$false
Afectado por -ErrorAction
Afectado por $ErrorActionPreference

Error de terminación de instrucciones

Los errores de terminación de instrucciones se pueden generar mediante ThrowTerminatingError(), errores del motor, excepciones de método de .NET o -ErrorAction Stop en contextos avanzados.

Atributo Descripción
Ámbito de impacto La instrucción actual se detiene; script continues
Atrapado por catch
Atrapado por trap
Agregado a $Error
Establece en $?$false
Afectado por -ErrorAction No (Break solo)
Afectado por $ErrorActionPreference Sí (puede suprimir)

Error de terminación de script

Los errores de terminación de scripts se pueden generar mediante throw, analizar errores o -ErrorAction Stop en contextos no avanzados.

Atributo Descripción
Ámbito de impacto Desenredado de pila de llamadas
Atrapado por catch
Atrapado por trap
Agregado a $Error
Establece en $?$false
Afectado por -ErrorAction No
Afectado por $ErrorActionPreference throw: Sí (puede suprimir)
Afectado por $ErrorActionPreference Escalado: depende del contexto

Consulte también