HOWTO · PowerShell

Comment mettre fin à un script dans Windows PowerShell

Découvrez quand employer exit, return, throw, break, continue ou Stop-Process pour arrêter la bonne portée et renvoyer un code fiable avec PowerShell.

Sur cette page

Mettre fin à un script PowerShell ne correspond pas à une seule opération. L’instruction appropriée dépend de ce qui doit s’arrêter : le processus du script, la fonction en cours, une itération ou un autre processus du système d’exploitation.

Objectif Instruction
Terminer le script principal et communiquer un état exit <code>
Quitter une fonction, un script ou un bloc de script return
Signaler une erreur que l’appelant peut intercepter throw
Quitter une boucle ou une instruction switch break
Passer à l’élément suivant d’une boucle ou de switch continue
Terminer un autre processus local Stop-Process

Terminer un script PowerShell avec exit

exit termine un script ou une instance PowerShell. Un entier facultatif devient le code de sortie du processus : par convention, 0 indique une réussite et une valeur différente de zéro un échec. Documentez chaque code d’erreur afin que les tâches planifiées, les travaux CI et les programmes appelants puissent réagir correctement.

Enregistrez ce script d’entrée sous Check-Config.ps1 :

param([Parameter(Mandatory)][string]$Path)

if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
    Write-Error "Configuration file not found: $Path"
    exit 2
}

Write-Output 'Configuration file found.'
exit 0

Exécutez-le comme processus enfant depuis une autre session PowerShell, puis lisez son état :

powershell.exe -NoProfile -File .\Check-Config.ps1 -Path .\missing.json
$LASTEXITCODE

La dernière commande affiche 2. Avec PowerShell 7, utilisez pwsh à la place de powershell.exe. PowerShell expose l’état du processus enfant dans $LASTEXITCODE ; un appelant cmd.exe le lit dans %ERRORLEVEL%.

Réservez exit à la limite du script principal. Si une fonction réutilisable appelle exit, elle risque de fermer une session interactive, un exécuteur de tests ou un autre hôte. Il vaut mieux que les fonctions renvoient des données ou lèvent des erreurs, puis que seul le script d’entrée transforme le résultat en code de sortie.

Quitter la portée actuelle avec return

return quitte la fonction, le script ou le bloc de script en cours. Cette instruction ne définit pas à elle seule un code de sortie de processus.

function Get-ConfigText {
    param([string]$Path)

    if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
        return $null
    }

    Get-Content -LiteralPath $Path -Raw
}

Dans une fonction PowerShell ordinaire, toute valeur non capturée du flux de réussite fait partie de la sortie, pas seulement l’expression qui suit return. Pour les diagnostics, employez Write-Verbose ou un flux adapté plutôt que d’émettre des chaînes supplémentaires avec Write-Output.

S’arrêter sur une erreur interceptable avec throw

throw crée par défaut une erreur qui termine le script et remonte la pile d’appels jusqu’à ce qu’un bloc catch ou une instruction trap la traite. Utilisez-le lorsqu’une fonction ne peut pas produire de résultat valide et que son appelant doit choisir la récupération.

function Get-RequiredConfig {
    param([string]$Path)

    if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
        throw "Configuration file not found: $Path"
    }

    Get-Content -LiteralPath $Path -Raw
}

try {
    $config = Get-RequiredConfig -Path '.\settings.json'
}
catch {
    Write-Error $_
    exit 2
}

Ce modèle sépare les responsabilités : la fonction décrit l’échec avec throw, tandis que le script d’entrée l’intercepte et choisit le code public. Toutes les erreurs de cmdlet n’atteignent pas automatiquement catch ; ajoutez -ErrorAction Stop à une erreur sans fin d’exécution lorsqu’elle doit y être traitée.

Employer break et continue uniquement dans les blocs de contrôle

break quitte la boucle ou le switch le plus proche. continue ignore la fin de l’itération actuelle et commence la suivante.

foreach ($name in 'alpha', '', 'beta', 'stop', 'omega') {
    if ([string]::IsNullOrWhiteSpace($name)) {
        continue
    }
    if ($name -eq 'stop') {
        break
    }
    Write-Output $name
}

Sortie :

alpha
beta

Ce ne sont pas des commandes générales de fin de script. En dehors d’une boucle, de switch ou de trap, PowerShell peut rechercher une structure englobante dans la pile d’appels et terminer le runspace courant s’il n’en trouve aucune.

Terminer un autre processus avec Stop-Process

Stop-Process cible un processus distinct sur l’ordinateur local ; il ne signifie pas « arrêter ce script ». Prévisualisez une sélection large avec -WhatIf :

Get-Process -Name notepad -ErrorAction SilentlyContinue |
    Stop-Process -WhatIf

Ne retirez -WhatIf qu’après avoir confirmé les cibles. Préférez un objet processus connu ou un PID lorsqu’un nom peut correspondre à plusieurs processus. L’arrêt du processus d’un autre utilisateur peut aussi nécessiter une session PowerShell élevée.

Conserver le code de sortie d’un programme natif

$? indique si la dernière commande PowerShell a réussi, tandis que $LASTEXITCODE contient le code de sortie du dernier programme natif. Enregistrez immédiatement cette valeur, car la commande native suivante peut l’écraser.

git status --porcelain
$gitCode = $LASTEXITCODE

if ($gitCode -ne 0) {
    Write-Error "git failed with exit code $gitCode"
    exit $gitCode
}

Utilisez return ou throw dans la logique réutilisable et réservez exit <code> à la limite du script principal. La sortie des fonctions, le flux de contrôle et l’état du processus restent ainsi distincts et prévisibles.

Préserver le nettoyage et distinguer l’annulation

Placez le nettoyage dans finally, et non après une ligne susceptible d’arrêter le traitement. D’après la documentation des mots-clés PowerShell, finally s’exécute si le travail de try réussit, si une erreur atteint catch, si exit est appelé ou si Ctrl+C interrompt le script; utilisez-le pour libérer un flux, un verrou ou un fichier temporaire.

$stream = $null

try {
    $stream = [System.IO.File]::OpenRead($Path)
    # Process the stream.
}
finally {
    if ($null -ne $stream) {
        $stream.Dispose()
    }
}

Laissez le code réutilisable faire throw ou return vers le script d’entrée afin que celui-ci nettoie et fixe le statut au même endroit. Ctrl+C, un travail arrêté et une entrée non valide sont des événements distincts : décidez et documentez si chacun est une annulation, un échec de validation ou un autre statut auquel un appelant ou planificateur doit répondre. Ne les réduisez pas silencieusement à un échec générique. L’arrêt d’un autre processus est différent : préférez l’arrêt normal de l’application. Stop-Process -Force peut empêcher le nettoyage de fichiers ou d’état; ne l’utilisez que si cette conséquence est comprise.

Garder les scripts enfants et les hôtes dans la portée prévue

L’opérateur d’appel exécute un script enfant dans sa propre portée; le dot-sourcing l’exécute dans la portée courante et importe ses fonctions et variables. Utilisez ce dernier uniquement pour importer des définitions.

# Run the child in its own script scope.
& .\Child.ps1

# Import definitions into the current scope.
. .\Functions.ps1

Un exit dans du code réutilisable peut fermer une session interactive, un exécuteur de tests ou un autre hôte. Un enfant lancé avec powershell.exe -File ou pwsh -File rend le contrôle à son appelant; une console interactive peut fermer sa session. Les runspaces incorporés et les éditeurs peuvent différer. Testez la commande réelle, notamment -File ou -Command, profils, guillemets, sortie et statut séparément.

Recommandation

Réservez exit <code> à la limite de niveau supérieur, return à la portée courante, throw à un échec gérable, break et continue à leur boucle ou switch, et Stop-Process à un processus local distinct. Des fonctions qui renvoient des données ou lèvent des erreurs restent réutilisables; un petit script d’entrée peut traduire le résultat pour le shell, le planificateur, la CI ou un programme enveloppe.