Freigeben über


about_Error_Handling

Kurzbeschreibung

Beschreibt die Arten von Fehlern in PowerShell und die Mechanismen für die Behandlung.

Lange Beschreibung

PowerShell unterscheidet drei Kategorien von Fehlern:

  • Nicht beendete Fehler
  • Fehler beim Beenden von Anweisungen
  • Skriptbeendungsfehler

Das Verständnis der Unterscheidung ist für das Schreiben zuverlässiger Skripts und Module unerlässlich, da jede Kategorie unterschiedliche Standardverhalten aufweist und unterschiedliche Behandlungstechniken erfordert.

Darüber hinaus melden externe (systemeigene) Programme Fehler über Exitcodes, die PowerShell separat von seinem eigenen Fehlersystem nachverfolgt.

Fehlertypen

Nicht beendete Fehler

Ein nicht beendeter Fehler meldet ein Problem, beendet die Pipeline jedoch nicht. Der Befehl verarbeitet weiterhin nachfolgende Eingabeobjekte. Nicht beendete Fehler werden durch:

  • Das Write-Error Cmdlet
  • Die $PSCmdlet.WriteError() Methode in erweiterten Funktionen
  • Cmdlets, die bei einzelnen Eingabeobjekten auf wiederherstellbare Fehler stoßen

Standardmäßig zeigt PowerShell die Fehlermeldung an und setzt die Ausführung fort.

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

In diesem Beispiel Get-Content wird ein nicht beendeter Fehler gemeldet noSuchFile.txt und anschließend die Verarbeitung file3.txtfortgesetzt.

Nicht beendete Fehler werden nicht ausgelöst oder trap standardmäßig nicht ausgelöstcatch.

Fehler beim Beenden von Anweisungen

Ein Anweisungsbeendfehler stoppt die ausführung der aktuellen Anweisung (Pipeline), die Ausführung wird jedoch bei der nächsten Anweisung im Skript fortgesetzt. Fehler beim Beenden von Anweisungen werden generiert durch:

  • Die $PSCmdlet.ThrowTerminatingError() Methode in erweiterten Funktionen und kompilierten Cmdlets
  • Modulfehler wie CommandNotFoundException (Aufrufen eines nicht vorhandenen Befehls) und ParameterBindingException (ungültige Parameterargumente)
  • .NET-Methodenaufrufe, die Ausnahmen auslösen, z. B. [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'

Fehler beim Beenden von Anweisungen können von try/catch und trap.

Hinweis

.ThrowTerminatingError() den Parameter nicht konsultieren -ErrorAction (mit Ausnahme des Break Werts, der den Debugger eingibt). $ErrorActionPreference Gilt jedoch für Anweisungsbeendungsfehler über den Handler auf Anweisungsebene des Moduls. Kann z. B. einen Anweisungsbeendfehler unterdrücken, $ErrorActionPreference = 'SilentlyContinue' sodass das Skript bei der nächsten Anweisung fortgesetzt wird. Der -ErrorAction Parameter kann dies nicht tun. Ausführliche Informationen finden Sie unter The $ErrorActionPreference asymmetrisch.

Skriptbeendungsfehler

Ein Skriptbeendfehler entspannt den gesamten Aufrufstapel. Die Ausführung wird vollständig beendet, es sei denn, der Fehler wird von einem Block oder trap einer try/catch Anweisung abgefangen. Skriptbeendungsfehler werden von folgenden Elementen generiert:

  • dem throw-Schlüsselwort
  • Analysieren von Fehlern (Syntaxfehler, die verhindern, dass das Skript kompiliert wird)
  • Nicht beendete Fehler werden von -ErrorAction Stop oder $ErrorActionPreference = 'Stop' in nicht erweiterten Kontexten eskaliert. Weitere Informationen finden Sie unter "Funktionsweise der Eskalation".
  • Bestimmte kritische Motorfehler
# 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)'

Das throw Schlüsselwort generiert standardmäßig einen Skriptbeendfehler. $ErrorActionPreference Kann jedoch bei throw Festlegung auf SilentlyContinue oder Ignore. Beim Aufrufen einer erweiterten Funktion wird -ErrorAction SilentlyContinueder Parameter in einen bereichslokalen $ErrorActionPreference Wert übersetzt, sodass er auch innerhalb dieser Funktion unterdrückt wird throw .

Hinweis

Selbst bei $ErrorActionPreference = 'Ignore', ein throw unterdrücktes wird immer noch ein Eintrag in $Error. Der Ignore Wert verhindert nur die $Error Aufzeichnung für nicht beendete Fehler.

Von Bedeutung

Die Begriffe "Anweisung beenden" und "Skriptbeendung " beschreiben den Wirkungsbereich, nicht den Schweregrad des Fehlers. Ein Anweisungsbeendfehler stoppt eine Anweisung. Ein Skriptbeendfehler stoppt das gesamte Skript und seine Aufrufer. Beide können von try/catch.

Fehler des externen Programms

Externe (systemeigene) Programme nehmen nicht direkt am Fehlersystem von PowerShell teil. Sie melden einen Fehler über einen Nicht-Null-Ausgangscode, der von PowerShell in der $LASTEXITCODE automatischen Variablen gespeichert wird.

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

Standardmäßig wird ein Nicht-Null-Exitcode aus einem systemeigenen Programm zurückgegeben:

  • Legt auf fest $?$false
  • Generiert keinErrorRecord In $Error
  • Löst nicht aus catch oder trap

PowerShell 7.3 hat die experimentelle Einstellungsvariable $PSNativeCommandUseErrorActionPreferencehinzugefügt, die in 7.4 zu einem stabilen Feature wurde. Wenn Sie diese Variable auf $truefestlegen, wird ein Nicht-Null-Beendigungscode einen nicht beendeten Fehler ausgegeben, dessen Meldung den spezifischen Beendigungscode (a NativeCommandExitException) angibt. Dieser Fehler berücksichtigt, sodass durch Festlegen des Fehlers $ErrorActionPreferenceder Fehler auf einen Skriptbeendungsfehler höher wird, der try/catchabgefangen werden kann.Stop

Fehlerstatusvariablen

PowerShell verwaltet mehrere automatische Variablen, die den aktuellen Fehlerstatus widerspiegeln.

$?

Enthält, $true ob der letzte Vorgang erfolgreich war und $false wenn ein Fehler (nicht beendet oder beendet) erzeugt wurde. Für systemeigene Befehle wird basierend auf dem Beendigungscode $? festgelegt: $true für Exit-Code 0, $false andernfalls.

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

$Error

Ein ArrayList Objekt, das die neuesten Fehlerdatensätze speichert, wobei der letzte Fehler am Index 0aufgetreten ist. Die Liste enthält bis zu $MaximumErrorCount Einträge (Standard 256).

Alle Beendigungsfehler werden hinzugefügt $Error. Zum Beenden von Fehlern wird die Anzeige unterdrückt, Ignore aber weiterhin der Fehler in $Error. Alle nicht beendeten Vorgänge werden hinzugefügt $Error , es sei denn -ErrorAction Ignore , sie werden bei nicht beendeten Fehlern verwendet, was sowohl die Anzeige als auch die Aufzeichnung verhindert.

$LASTEXITCODE

Enthält den Exitcode des letzten systemeigenen Programms, das ausgeführt wurde. Ein Wert von 0 konventionell zeigt erfolglos an. Jeder Wert ungleich Null gibt einen Fehler an. Diese Variable ist nicht von PowerShell-Cmdlet-Fehlern betroffen.

Steuerelementfehlerverhalten

Der -ErrorAction allgemeine Parameter

Die -ErrorAction allgemeinen Parameterüberschreibungen $ErrorActionPreference für einen einzelnen Befehl. Sie steuert, wie PowerShell auf nicht beendete Fehler dieses Befehls reagiert.

Wert Verhalten
Continue Anzeigen des Fehlers und Fortsetzen (Standard)
SilentlyContinue Anzeige unterdrücken, hinzufügen $Error, fortfahren
Ignore Anzeige unterdrücken und nicht hinzufügen $Error
Stop Eskalieren zu einem Abbruchfehler (siehe Funktionsweise der Eskalation)
Inquire Benutzer auffordern, eine Entscheidung zu treffen
Break Geben Sie den Debugger ein.

-ErrorAction ändert nicht das Verhalten von Fehlern, die von $PSCmdlet.ThrowTerminatingError(). Diese Fehler werden unabhängig von der Einstellung des Aufrufers immer von der Anweisung beendet.

Die $ErrorActionPreference Variable

Die $ErrorActionPreference Einstellungsvariable gilt für alle Befehle im aktuellen Bereich und untergeordneten Bereichen. Sie akzeptiert dieselben Werte wie -ErrorAction.

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

Wenn -ErrorAction für einen Befehl angegeben wird, hat er Vorrang $ErrorActionPreference vor diesem Befehl.

Funktionsweise der Eskalation

Wenn -ErrorAction Stop oder $ErrorActionPreference = 'Stop' in Kraft ist, wandelt PowerShell nicht beendete Fehler mithilfe des folgenden Mechanismus in Beendigungsfehler um:

  1. Ein Cmdlet ruft WriteError() intern auf, um einen nicht beendeten Fehler auszustrahlen.
  2. Das Modul überprüft die effektive ErrorAction Einstellung für den Befehl.
  3. Da die Einstellung lautet Stop, erstellt das Modul einen ActionPreferenceStopException , der den ursprünglichen Fehlerdatensatz umschließt.
  4. Wenn sie abgefangen catchwerden, können Sie auf die ursprünglichen Fehlerinformationen zugreifen $_.Exception.ErrorRecord.

Der Umfang des eskalierten Fehlers hängt vom Kontext ab:

  • In nicht erweiterten Skripts, Funktionen oder Skriptblöcken eskaliert die Einstellung $ErrorActionPreference = 'Stop' auf einen Skriptbeendfehler . Der Fehler verteilt den Aufrufstapel.
  • In erweiterten Funktionen und Skriptblöcken (denen mit [CmdletBinding()]) bleibt der Fehler anweisungsbeend. Die Ausführung wird nach dem Aufruf an der nächsten Anweisung fortgesetzt.
  • Das Übergeben -ErrorAction Stop an eine erweiterte Funktion hat die gleiche Auswirkung wie die Einstellung $ErrorActionPreference = 'Stop' darin, da -ErrorAction sie in einen bereichslokalen $ErrorActionPreference Wert übersetzt wird.

Eskalationsbeispiele

  • NICHT erweitert: Skriptbeendung ('after' wird NICHT gedruckt)

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

    & {
        [CmdletBinding()]
        param()
        $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath'
    } 2>$null
    'after'
    
  • Ohne -ErrorAction Stop: nicht beendet, wird "Catch" nicht ausgeführt.

    try {
        Write-Error 'This is non-terminating'
        Write-Output 'Execution continues'
    } catch {
        Write-Output "Caught: $_"   # Not reached
    }
    
  • Mit -ErrorAction Stop: eskaliert bis zum Beenden

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

Eskalierte Fehler können von ihrem ursprünglichen Ausnahmetyp abgefangen werden. Das Modul entpackt die ActionPreferenceStopException zugrunde liegende Ausnahme:

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

Die $ErrorActionPreference Asymmetrie

Der -ErrorAction Parameter und die $ErrorActionPreference Variable verhalten sich bei Beendigungsfehlern anders. Es ist wichtig, diese Asymmetrie zu verstehen:

  • -ErrorAction wirkt sich nur auf nicht beendete Fehler aus . Wenn ein Cmdlet aufruft $PSCmdlet.ThrowTerminatingError(), wird der -ErrorAction Parameter ignoriert (mit Ausnahme Breakder Eingabe des Debuggers). Der Fehler wird immer ausgelöst.

  • $ErrorActionPreference wirkt sich sowohl auf Nichtbeendungs- als auch auf Anweisungsbeendungsfehler aus. Der Fehlerhandler auf Anweisungsebene des Moduls $ErrorActionPreference liest (nicht der -ErrorAction Parameter) und kann einen Anweisungsbeendfehler unterdrücken, wenn der Wert ist SilentlyContinue oder 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'

Von Bedeutung

$ErrorActionPreferenceFehler, die auf " festgelegt" festgelegt truesindSuppressPromptInInterpreter, können nicht unterdrückt werden. Diese werden unabhängig von der Einstellungsvariable immer weitergegeben. Beispiele für diesen Fehlertyp sind:

  • ActionPreferenceStopException aus -ErrorAction Stop Eskalation
  • Fehler innerhalb von PowerShell-Klassenmethoden
  • PipelineStoppedException

Fehler behandeln

try/catch/finally

Wird verwendet try/catch/finally , um Fehler beim Beenden von Anweisungen und Skripts zu behandeln. Wenn innerhalb eines try Blocks ein Fehler auftritt, sucht PowerShell nach einem übereinstimmenden catch Block. Der finally Block wird immer ausgeführt, unabhängig davon, ob ein Fehler aufgetreten ist.

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
}

Innerhalb eines try Blocks legt das Modul ein internes Kennzeichen fest, das zu nicht beendeten Fehlern führt, die von -ErrorAction Stop oder $ErrorActionPreference = 'Stop' an den catch Block weitergegeben werden. Dies ist ein Designverhalten, kein Sonderfall.

Vollständige Syntaxdetails finden Sie unter about_Try_Catch_Finally.

trap

Die trap Anweisung behandelt Beendigungsfehler auf Der Bereichsebene. Wenn an einer beliebigen Stelle im eingeschlossenen Bereich ein Fehler auftritt, wird der trap Block ausgeführt.

  • Standard (nein break oder continue): Der Fehler wird angezeigt, und die Ausführung wird bei der nächsten Anweisung nach der Anweisung fortgesetzt, die den Fehler verursacht hat.
  • continue in the trap: Suppresses the error message and resumes at the next statement.
  • break in der Falle: Der Fehler wird an den übergeordneten Bereich weitergegeben.
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'

Vollständige Syntaxdetails finden Sie unter about_Trap.

Melden von Fehlern in Funktionen und Skripts

Wählen Sie beim Schreiben von Funktionen und Skripts den Fehlerberichterstattungsmechanismus aus, der dem Schweregrad des Fehlers entspricht.

Nicht beendet – Verwendung Write-Error

Wird verwendet Write-Error , wenn die Funktion die Verarbeitung anderer Eingaben fortsetzen kann. Dies ist für Pipelinefunktionen geeignet, die mehrere Objekte verarbeiten und fehler bei einzelnen Elementen auftreten.

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

Hinweis

Verwenden Sie $PSCmdlet.WriteError() in erweiterten Funktionen (mit [CmdletBinding()]denen), statt Write-Error sicherzustellen, dass sie $? im Bereich des Aufrufers ordnungsgemäß festgelegt $false ist. Das Write-Error Cmdlet ist nicht immer richtig festgelegt $? .

Anweisungsbeendung – Verwenden $PSCmdlet.ThrowTerminatingError()

Wird verwendet $PSCmdlet.ThrowTerminatingError() , wenn die Funktion überhaupt nicht fortgesetzt werden kann, aber der Aufrufer sollte entscheiden, wie der Fehler behandelt werden soll. Dies ist der empfohlene Ansatz in erweiterten Funktionen.

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
}

Nachdem der Fehler die Funktion verlassen hat, behandelt der Aufrufer sie standardmäßig als nicht beendeten Fehler. Der Anrufer kann eskalieren mit -ErrorAction Stop.

Skriptbeendung – Verwenden throw

Verwenden Sie diese Einstellung throw , wenn die Wiederherstellung nicht möglich ist und das gesamte Skript beendet werden soll.

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

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

Welcher Mechanismus verwendet werden soll

  • Bei der Verarbeitung mehrerer Eingaben, bei denen einige fehlschlagen, verwenden Write-Error oder $PSCmdlet.WriteError().
  • Wenn die Funktion nicht fortgesetzt werden kann, verwenden $PSCmdlet.ThrowTerminatingError() Sie die Funktion, und lassen Sie den Aufrufer entscheiden, wie sie behandelt werden soll.
  • Wenn das gesamte Skript sofort beendet werden muss, verwenden Sie throw.

Zusammenfassung der Fehlertypen

In den folgenden Tabellen sind die Eigenschaften und Verhaltensweisen der verschiedenen Fehlertypen in PowerShell zusammengefasst.

Nicht beendeter Fehler

Nicht beendete Fehler können von Write-Error oder $PSCmdlet.WriteError().

Merkmal Beschreibung
Wirkungsbereich Pipeline wird fortgesetzt
Gefangen von catch Nein (es sei denn, eskaliert)
Gefangen von trap Nein (es sei denn, eskaliert)
Hinzugefügt zu $Error Ja (es sei denn Ignore, )
Legt auf fest $?$false Ja
Betroffen von -ErrorAction Ja
Betroffen von $ErrorActionPreference Ja

Fehler beim Beenden der Anweisung

Fehler beim Beenden von Anweisungen können durch ThrowTerminatingError()Modulfehler, .NET-Methodenausnahmen oder -ErrorAction Stop in erweiterten Kontexten generiert werden.

Merkmal Beschreibung
Wirkungsbereich Aktuelle Anweisung stoppt; Skript wird fortgesetzt
Gefangen von catch Ja
Gefangen von trap Ja
Hinzugefügt zu $Error Ja
Legt auf fest $?$false Ja
Betroffen von -ErrorAction Nein (Break nur)
Betroffen von $ErrorActionPreference Ja (kann unterdrückt werden)

Skriptbeendungsfehler

Skriptbeendungsfehler können durch throwAnalysefehler oder -ErrorAction Stop in nicht erweiterten Kontexten generiert werden.

Merkmal Beschreibung
Wirkungsbereich Anrufstapel entspannt sich
Gefangen von catch Ja
Gefangen von trap Ja
Hinzugefügt zu $Error Ja
Legt auf fest $?$false Ja
Betroffen von -ErrorAction No
Betroffen von $ErrorActionPreference throw: Ja (kann unterdrückt werden)
Betroffen von $ErrorActionPreference Eskaliert: hängt vom Kontext ab

Siehe auch