En regardant un script Get-WebFile sur PoshCode: http://poshcode.org/3226 J’ai remarqué ce truc étrange:
$URL_Format_Error = [ssortingng]"..." Write-Error $URL_Format_Error return
Quelle est la raison de ceci par opposition à:
$URL_Format_Error = [ssortingng]"..." Throw $URL_Format_Error
ou même mieux:
$URL_Format_Error = New-Object System.FormatException "..." Throw $URL_Format_Error
Si je comprends bien, vous devez utiliser Write-Error pour les erreurs non terminantes et Throw pour les erreurs de terminaison. Il me semble donc que vous ne devez pas utiliser Write-Error suivi de Return. Y a-t-il une différence?
Write-Error
doit être utilisé si vous souhaitez informer l’utilisateur d’une erreur non critique. Par défaut, tout ce qu’il fait est d’imprimer un message d’erreur en texte rouge sur la console. Cela n’empêche pas un pipeline ou une boucle de continuer. Throw
par contre produit ce qu’on appelle une erreur de terminaison. Si vous utilisez jet, le pipeline et / ou la boucle de courant seront terminés. En fait, toute exécution sera terminée à moins que vous n’utilisiez une structure trap
ou try/catch
pour gérer l’erreur de fin.
Il y a une chose à noter, si vous définissez $ErrorActionPreference
sur "Stop"
et utilisez Write-Error
cela produira une erreur de fin .
Dans le script que vous avez lié, nous trouvons ceci:
if ($url.Contains("http")) { $request = [System.Net.HttpWebRequest]::Create($url) } else { $URL_Format_Error = [ssortingng]"Connection protocol not specified. Recommended action: Try again using protocol (for example 'http://" + $url + "') instead. Function aborting..." Write-Error $URL_Format_Error return }
Il semble que l’auteur de cette fonction ait voulu arrêter l’exécution de cette fonction et afficher un message d’erreur à l’écran, mais ne voulait pas que tout le script cesse de s’exécuter. L’auteur du script aurait pu utiliser throw
mais cela signifierait que vous devez utiliser un try/catch
lors de l’appel de la fonction.
return
quittera la scope actuelle qui peut être une fonction, un script ou un bloc de script. Ceci est mieux illustré avec le code:
# A foreach loop. foreach ( $i in (1..10) ) { Write-Host $i ; if ($i -eq 5) { return } } # A for loop. for ($i = 1; $i -le 10; $i++) { Write-Host $i ; if ($i -eq 5) { return } }
Sortie pour les deux:
1 2 3 4 5
Un getcha ici utilise return
avec ForEach-Object
. Cela ne cassera pas le traitement comme on pourrait s’y attendre.
Plus d’informations:
$ErrorActionPreference
: http://technet.microsoft.com/en-us/library/dd347731.aspx try/catch
: http://technet.microsoft.com/en-us/library/dd315350.aspx trap
: http://technet.microsoft.com/en-us/library/dd347548.aspx throw
: http://technet.microsoft.com/en-us/library/dd819510.aspx return
: http://technet.microsoft.com/en-us/library/dd347592.aspx La principale différence entre l’applet de commande Write-Error et le mot-clé throw dans PowerShell est que le premier imprime simplement du texte dans le stream d’erreur standard (stderr) , tandis que le second termine le traitement de la commande ou de la fonction en cours d’exécution. par PowerShell en envoyant des informations sur l’erreur à la console.
Vous pouvez observer le comportement différent des deux dans les exemples que vous avez fournis:
$URL_Format_Error = [ssortingng]"..." Write-Error $URL_Format_Error return
Dans cet exemple, le mot clé return
a été ajouté pour arrêter explicitement l’exécution du script après l’envoi du message d’erreur à la console. Dans le second exemple, en revanche, le mot-clé return
n’est pas nécessaire car la terminaison est implicitement effectuée par throw
:
$URL_Format_Error = New-Object System.FormatException "..." Throw $URL_Format_Error
Important : Il existe 2 types d’erreurs de terminaison , que les rubriques d’aide actuelles confondent malheureusement:
erreurs liées à la suppression d’ instruction , telles qu’elles sont signalées par les applets de commande dans certaines situations non récupérables et par les expressions dans lesquelles une erreur d’exécution / .NET PS se produit; seule l’ instruction est terminée et l’ exécution du script continue par défaut .
des erreurs de script- sortingggering , soit déclenchées par Throw
soit en augmentant l’un des autres types d’erreur via la variable de préférence action-action / la valeur du paramètre Stop
.
À moins d’être attrapés, ils terminent le thread d’exécution en cours (c.-à-d. Pas seulement le script en cours, mais tous ses appelants, le cas échéant).
Pour une présentation complète de la gestion des erreurs de PowerShell, consultez ce problème de documentation de GitHub .
Le rest de cet article se concentre sur les erreurs non terminales par rapport aux erreurs de terminaison d’instruction .
Pour compléter les réponses utiles existantes en mettant l’accent sur l’essentiel de la question: comment choisissez- vous de signaler une erreur de fin ou de non-terminaison ?
Cmdlet Error Reporting contient des instructions utiles; laissez-moi tenter un résumé pragmatique :
L’idée générale derrière les erreurs non terminales est de permettre le traitement “tolérant aux pannes” de grands ensembles d’entrées : le traitement d’un sous-ensemble des objects d’entrée ne devrait pas (par défaut) interrompre le processus – potentiellement de longue durée – dans son ensemble, vous permettant d’inspecter les erreurs et de ne retraiter que les objects défaillants ultérieurement – comme indiqué dans les enregistrements d’erreur collectés dans la variable automatique $Error
.
Signalez une erreur NON TERMINATOIRE si votre applet de commande / fonction avancée:
$PSCmdlet.WriteError()
pour signaler une erreur sans fin ( Write-Error
, malheureusement, ne définit pas $False
dans la scope de l’ appelant – voir ce problème GitHub ). $?
vous indique si la commande la plus récente a signalé au moins une erreur non terminée.
$?
Être $False
peut signifier que n’importe quel sous – ensemble (non vide) d’objects d’entrée n’a pas été correctement traité, peut-être l’ensemble entier. $ErrorActionPreference
et / ou paramètre de cmdlet commun -ErrorAction
peut modifier le comportement des erreurs non terminantes (uniquement) en termes de comportement de sortie d’erreur et si les erreurs non terminantes doivent être renvoyées à des erreurs de script . Signaler une erreur STATEMENT-TERMINATING dans tous les autres cas .
$PSCmdlet.ThrowTerminatingError()
pour générer une erreur de fin de déclaration. Throw
génère en revanche une erreur d’interruption de script qui annule l’ intégralité du script . try/catch
handler ou trap
peut être utilisée (qui ne peut pas être utilisée avec des erreurs non terminantes ), mais notez que même les erreurs de fin de commande par défaut n’empêchent pas l’exécution du rest du script . Comme avec les erreurs non terminales , $?
reflète $False
si l’instruction précédente a déclenché une erreur de fin d’instruction. Malheureusement, toutes les cmdlets de base de PowerShell ne respectent pas ces règles :
Bien qu’improbable, New-TemporaryFile
(PSv5 +) signalerait une erreur non résiliante en cas d’échec, même s’il n’acceptait pas l’entrée de pipeline et ne produisait qu’un seul object de sortie – cela changerait probablement en v6: voir ce problème GitHub .
L’aide de Resume-Job
indique que le fait de transmettre un type de travail non pris en charge (par exemple, un travail créé avec Start-Job
, qui n’est pas pris en charge car Resume-Job
s’applique uniquement aux travaux de workflow ) entraîne une erreur de terminaison. PSv5.1.
Write-Error
permet au consommateur de la fonction de supprimer le message d’erreur avec -ErrorAction SilentlyContinue
(alternativement -ea 0
). Bien que throw
nécessite un try{...} catch {..}
Pour utiliser un try … catch with Write-Error
:
try { SomeFunction -ErrorAction Stop } catch { DoSomething }
Ajout à la réponse d’Andy Arismendi :
Le fait que Write-Error termine ou non le processus dépend du paramètre $ErrorActionPreference
.
Pour les scripts non sortingviaux, $ErrorActionPreference = "Stop"
est un paramètre recommandé pour échouer rapidement.
“Le comportement par défaut de PowerShell vis-à-vis des erreurs, qui doit continuer en cas d’erreur … se sent très VB6” On Error Resume Next “-ish”
(extrait de http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/ )
Cependant, les appels en Write-Error
terminent.
Pour utiliser Write-Error en tant que commande sans terminaison indépendamment des autres parameters d’environnement, vous pouvez utiliser le paramètre commun -ErrorAction
avec la valeur Continue
:
Write-Error "Error Message" -ErrorAction:Continue
Si votre lecture du code est correcte, vous avez raison. Les erreurs de terminaison doivent utiliser throw
, et si vous utilisez des types .NET, il est utile de suivre également les conventions d’exception .NET.