Als ich mir ein Get-WebFile-Skript auf PoshCode ( http://poshcode.org/3226) ansah, bemerkte ich diese für mich seltsame Erfindung :
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return
Was ist der Grund dafür im Gegensatz zu den folgenden?
$URL_Format_Error = [string]"..."
Throw $URL_Format_Error
Oder noch besser:
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
Soweit ich weiß, sollten Sie Write-Error für nicht terminierende Fehler und Throw für terminierende Fehler verwenden. Daher sollten Sie meines Erachtens keinen Write-Error gefolgt von Return verwenden. Ist da ein Unterschied?
powershell
error-handling
powershell-2.0
Bill Barry
quelle
quelle
return
sie nicht in dem an den Aufrufer zurückgebenprocess
Block einer (Fortgeschrittene) Funktion; Stattdessen wird mit dem nächsten Eingabeobjekt in der Pipeline fortgefahren. Dies ist in der Tat das typische Szenario für die Erzeugung nicht beendender Fehler: Wenn die Verarbeitung weiterer Eingabeobjekte noch möglich ist.Throw
ein Skript-Abschlussfehler generiert wird, der nicht mit den Anweisungs-Abschlussfehlern identisch ist, die beispielsweise durchGet-Item -NoSuchParameter
oder ausgelöst werden1 / 0
.Antworten:
Write-Error
sollte verwendet werden, wenn Sie den Benutzer über einen unkritischen Fehler informieren möchten. Standardmäßig wird lediglich eine Fehlermeldung in roter Schrift auf der Konsole gedruckt. Es verhindert nicht, dass eine Pipeline oder eine Schleife fortgesetzt wird.Throw
erzeugt andererseits einen sogenannten Abbruchfehler. Wenn Sie throw verwenden, werden die Pipeline und / oder die Stromschleife beendet. Tatsächlich wird die gesamte Ausführung beendet, es sei denn, Sie verwenden einetrap
oder einetry/catch
Struktur, um den Beendigungsfehler zu behandeln.Es ist eine Sache zu beachten, wenn Sie festgelegt
$ErrorActionPreference
zu"Stop"
verwenden ,Write-Error
wird es einen Abschlussfehler erzeugen .In dem Skript, mit dem Sie verlinkt haben, finden wir Folgendes:
Es sieht so aus, als wollte der Autor dieser Funktion die Ausführung dieser Funktion stoppen und eine Fehlermeldung auf dem Bildschirm anzeigen, wollte aber nicht, dass das gesamte Skript nicht mehr ausgeführt wird. Der Skriptautor hätte verwenden können,
throw
dies würde jedoch bedeuten, dass Sietry/catch
beim Aufrufen der Funktion a verwenden müssten .return
beendet den aktuellen Bereich, der eine Funktion, ein Skript oder ein Skriptblock sein kann. Dies lässt sich am besten mit Code veranschaulichen:Ausgabe für beide:
Ein Gotcha hier verwendet
return
mitForEach-Object
. Die Verarbeitung wird nicht wie erwartet unterbrochen.Mehr Informationen:
$ErrorActionPreference
: about_Preference_Variablestry/catch
: about_Try_Catch_Finallytrap
: about_Trapthrow
: about_Throwreturn
: about_Returnquelle
return
.Der Hauptunterschied zwischen dem Write-Error cmdlet und dem throw Schlüsselwort in Power ist , dass erstere einfach druckt einen Text auf den Standardfehlerstrom (Stderr) , während die letzteren tatsächlich beenden die Verarbeitung des laufenden Befehls oder eine Funktion, welche dann abgewickelt von PowerShell durch Senden von Informationen über den Fehler an die Konsole.
Sie können das unterschiedliche Verhalten der beiden in den von Ihnen bereitgestellten Beispielen beobachten:
In diesem Beispiel wurde das
return
Schlüsselwort hinzugefügt, um die Ausführung des Skripts explizit zu stoppen, nachdem die Fehlermeldung an die Konsole gesendet wurde. Im zweiten Beispiel ist dasreturn
Schlüsselwort hingegen nicht erforderlich, da die Beendigung implizit erfolgt durchthrow
:quelle
[System.Management.Automation.ErrorRecord]
$Error
$Error[0]
Write-Error
[System.Management.Automation.ErrorRecord]
Wichtig : Es gibt 2 Arten von Beendigungsfehlern , die in den aktuellen Hilfethemen leider zusammengeführt werden :
Anweisung -terminating Fehler, wie durch cmdlets in bestimmten Situationen nicht behebbaren gemeldet und durch Ausdrücke in dem eine Ausnahme .NET / a PS Laufzeitfehler auftritt; nur der Anweisung wird beendet und die Skriptausführung wird standardmäßig fortgesetzt .
Skript- terminierende Fehler (genauer: Runspace abbreche ), entweder getriggert durch
Throw
oder durch eine der anderen Fehlertypen über fehler Aktion Präferenz-Variable / Parameterwert eskaliertStop
.Sofern sie nicht abgefangen werden, beenden sie den aktuellen Runspace (Thread). Das heißt, sie beenden nicht nur das aktuelle Skript, sondern gegebenenfalls auch alle Aufrufer.
Eine umfassende Übersicht über die Fehlerbehandlung von PowerShell finden Sie in dieser GitHub-Dokumentation .
Der Rest dieses Beitrags konzentriert sich auf das Nichtbeenden und nicht auf Anweisungen endende Fehler.
Um die vorhandenen hilfreichen Antworten mit einem Fokus auf den Kern der Frage zu ergänzen: Wie wählen Sie aus , ob eine Aussage beendet werden soll? oder ein nichtbeendender Fehler werden soll ?
Cmdlet-Fehlerberichterstattung enthält hilfreiche Richtlinien. Lassen Sie mich eine pragmatische Zusammenfassung versuchen :
Die allgemeine Idee hinter nicht-Abschlussfehler ist „fehlertolerant“ Verarbeitung von großen Eingangssätzen zu ermöglichen : Ausfall eines verarbeiten Teilmenge der Eingangsobjekte sollten nicht (standardmäßig) Abbruch der - möglicherweise mit langer Laufzeit - Prozess als Ganzes , So können Sie die Fehler überprüfen und nur die fehlgeschlagenen erneut verarbeiten später Objekte erneut verarbeiten - wie über die in der automatischen Variablen gesammelten gemeldet
$Error
.Bericht a NON-TERMINATING- Fehler, wenn Ihr Cmdlet / Ihre erweiterte Funktion:
$PSCmdlet.WriteError()
in erweiterten Funktionen, um einen nicht terminierenden Fehler zu melden (diesWrite-Error
führt leider nicht dazu$?
, dass er$False
im Bereich des Aufrufers festgelegt wird - siehe dieses GitHub-Problem ).$?
Gibt an, ob der letzte Befehl mindestens einen nicht terminierenden Fehler gemeldet hat .$?
ist$False
kann entweder bedeuten , daß eine beliebige (nicht leer) Subset von Eingabeobjekten wurden nicht korrekt verarbeitet, möglicherweise das gesamte Set.$ErrorActionPreference
Voreinstellungsvariable und / oder der allgemeine Cmdlet-Parameter-ErrorAction
können das Verhalten von nicht terminierenden Fehlern (nur) in Bezug auf das Fehlerausgabeverhalten und die Frage ändern, ob nicht terminierende Fehler zu Skript -terminierenden Fehlern eskaliert werden sollen.In allen anderen Fällen einen STATEMENT-TERMINATING- Fehler melden .
$PSCmdlet.ThrowTerminatingError()
, um einen Anweisungsbeendigungsfehler zu generieren.Throw
Schlüsselwort im Gegensatz dazu einen Skript-Abschlussfehler generiert , der das gesamte Skript abbricht (technisch: der aktuelle Thread ).try/catch
Handler oder einetrap
Anweisung verwendet werden (die nicht mit nicht beendenden Fehlern verwendet werden kann). Beachten Sie jedoch, dass selbst Anweisungsbeendigungsfehler standardmäßig nicht die Ausführung des restlichen Skripts verhindern. Wie bei nicht terminierenden Fehlern wird$?
angezeigt,$False
ob die vorherige Anweisung einen Anweisungsbeendigungsfehler ausgelöst hat.Leider spielen nicht alle PowerShell-eigenen Cmdlets nach diesen Regeln :
Obwohl es unwahrscheinlich ist, dass ein Fehler
New-TemporaryFile
auftritt , meldet (PSv5 +) einen nicht terminierenden Fehler, wenn er fehlschlägt, obwohl keine Pipeline-Eingabe akzeptiert und nur ein Ausgabeobjekt erstellt wird. Dies wurde jedoch ab mindestens PowerShell [Core] 7.0 korrigiert: siehe GitHub Problem .Resume-Job
In der Hilfe wird behauptet, dass das Übergeben eines nicht unterstützten Jobtyps (z. B. eines mit erstellten JobsStart-Job
, der nicht unterstützt wird, da erResume-Job
nur für Workflow- Jobs gilt) einen Beendigungsfehler verursacht. Dies gilt jedoch nicht für PSv5.1.quelle
Write-Error
ermöglicht dem Verbraucher der Funktion, die Fehlermeldung mit-ErrorAction SilentlyContinue
(alternativ-ea 0
) zu unterdrücken . Währendthrow
erfordert eintry{...} catch {..}
Um einen Versuch zu verwenden ... fangen Sie mit
Write-Error
:quelle
Ergänzung zu Andy Arismendis Antwort :
Ob Write-Error den Prozess beendet oder nicht, hängt von der
$ErrorActionPreference
Einstellung ab.Für nicht triviale Skripte
$ErrorActionPreference = "Stop"
wird eine Einstellung empfohlen , die schnell fehlschlägt.(von http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/ )
Allerdings macht es
Write-Error
Anrufe zu beenden.Um Write-Error unabhängig von anderen Umgebungseinstellungen als nicht abschließenden Befehl zu verwenden, können Sie einen gemeinsamen Parameter
-ErrorAction
mit dem folgenden Wert verwendenContinue
:quelle
Wenn Sie den Code richtig gelesen haben, sind Sie richtig. Das Beenden von Fehlern sollte verwendet
throw
werden. Wenn Sie mit .NET-Typen arbeiten, ist es hilfreich, auch die .NET-Ausnahmekonventionen zu befolgen.quelle