Comment arrêter un script PowerShell sur la première erreur?

je veux que mon script PowerShell s'arrête lorsque l'une des commandes que j'exécute échoue (comme set -e en bash). J'utilise à la fois des commandes Powershell ( New-Object System.Net.WebClient ) et des programmes ( .setup.exe ).

175
demandé sur Joey 2012-03-30 22:27:33

5 réponses

$ErrorActionPreference = "Stop" vous permettra une partie du chemin (i.e. cela fonctionne très bien pour les cmdlets).

Cependant pour les ex, vous devrez vérifier vous-même $LastExitCode après chaque invocation de exe et déterminer si cela a échoué ou non. Malheureusement, Je ne pense pas que PowerShell peut aider ici parce que sur Windows, les ex ne sont pas terriblement cohérent sur ce qui constitue un" succès "ou" échec " code de sortie. La plupart suivent le standard UNIX de 0 indiquant le succès mais pas tous le font. Consultez la fonction Checklastexastexitcode dans ce billet de blog . Vous trouverez peut-être utile.

210
répondu Keith Hill 2017-06-22 20:03:50

vous devriez être capable d'accomplir ceci en utilisant la déclaration $ErrorActionPreference = "Stop" au début de vos scripts.

le paramètre par défaut de $ErrorActionPreference est Continue , c'est pourquoi vous voyez vos scripts continuer après que des erreurs se soient produites.

57
répondu goric 2012-03-30 19:11:09

malheureusement, en raison de cmdlets buggy comme New-RegKey et Clear-Disk , aucune de ces réponses ne sont suffisantes. J'ai actuellement installé sur les lignes suivantes en haut de script powershell pour maintenir ma santé mentale.

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'

et alors n'importe quel appel natif obtient ce traitement:

native_call.exe
$native_call_success = $?
if (-not $native_call_success)
{
    throw 'error making native call'
}

Ce modèle d'appel indigène devient lentement assez commun pour moi que je devrais probablement examiner les options pour le rendre plus concis. Je suis toujours un débutant en powershell, donc les suggestions sont les bienvenues.

7
répondu aggieNick02 2017-06-28 19:21:47

vous avez besoin d'un traitement d'erreur légèrement différent pour les fonctions powershell et pour appeler exe, et vous devez être sûr de dire à l'appelant de votre script qu'il a échoué. En s'appuyant sur Exec de la bibliothèque Psake, un script qui a la structure ci-dessous s'arrêtera sur toutes les erreurs, et est utilisable comme modèle de base pour la plupart des scripts.

Set-StrictMode -Version latest
$ErrorActionPreference = "Stop"


# Taken from psake https://github.com/psake/psake
<#
.SYNOPSIS
  This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode
  to see if an error occcured. If an error is detected then an exception is thrown.
  This function allows you to run command-line programs without having to
  explicitly check the $lastexitcode variable.
.EXAMPLE
  exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed"
#>
function Exec
{
    [CmdletBinding()]
    param(
        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,
        [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ("Error executing command {0}" -f $cmd)
    )
    & $cmd
    if ($lastexitcode -ne 0) {
        throw ("Exec: " + $errorMessage)
    }
}

Try {

    # Put all your stuff inside here!

    # powershell functions called as normal and try..catch reports errors 
    New-Object System.Net.WebClient

    # call exe's and check their exit code using Exec
    Exec { setup.exe }

} Catch {
    # tell the caller it has all gone wrong
    $host.SetShouldExit(-1)
    throw
}
3
répondu alastairtree 2018-02-27 00:07:49

je suis venu ici pour la même chose. $ErrorActionPreference= "Stop" tue mon shell immédiatement quand je préfère voir le message d'erreur (pause) avant qu'il ne se termine. Repli sur mes sensibilités de fournée:

IF %ERRORLEVEL% NEQ 0 pause & GOTO EOF

j'ai trouvé que cela fonctionne à peu près la même chose pour mon script ps1 particulier:

Import-PSSession $Session
If ($? -ne "True") {Pause; Exit}
1
répondu harvey263 2017-09-01 21:41:07