Terminer un script dans PowerShell

394

J'ai cherché un moyen de terminer un script PowerShell (PS1) lorsqu'une erreur irrécupérable se produit dans une fonction. Par exemple:

function foo() {
    # Do stuff that causes an error
    $host.Exit()
}

Bien sûr, il n'y a rien de tel $host.Exit(). Oui $host.SetShouldExit(), mais cela ferme la fenêtre de la console, ce qui n'est pas ce que je veux. Ce dont j'ai besoin est quelque chose d'équivalent à Python sys.exit()qui arrêtera simplement l'exécution du script actuel sans plus tarder.

Edit: Ouais, c'est juste exit. Duh.

kprobst
la source
8
Si vous voulez éviter de fermer la fenêtre PowerShell ou ISE dans mon cas; utilisez plutôt "retour". Il termine simplement le contexte en cours d'exécution. "New guy" explique en détail toutes les options à des fins éducatives; vous voudrez peut-être envisager de modifier votre réponse acceptée (a actuellement plus de votes positifs) pour les futurs utilisateurs de StackOverflow. Cela vous permettra également de déboguer le script.
ZaxLofful
Est-ce que cela répond à votre question? Qu'est-ce que la «sortie» dans PowerShell?
Mark Schultheiss

Réponses:

389

Vous devez utiliser le exitmot - clé .

Michael Bray
la source
15
Putain de merde, si je n'étais pas tellement pris à essayer de comprendre comment faire ces choses intelligemment, j'aurais probablement essayé cela pour commencer et compris que cela fonctionne :) Merci.
kprobst
118
Comment est-ce la réponse acceptée? Il ne "ferme la fenêtre de la console" que le demandeur a dit "ce n'est pas ce que je veux".
claudekennilol
3
@claudekennilol Seul le demandeur de questions peut accepter une réponse. Soit ils ont raté le fait que la sortie est censée fermer la fenêtre, soit ils ont changé d'avis et ont jugé cela acceptable pour leur objectif.
Iszi
3
Il ne ferme pas la fenêtre de la console en v3 ou v4, que j'utilise. Eh bien, ce sera le cas si vous exécutez le script depuis l'explorateur, mais peu importe la façon dont vous terminez le script, il le fera. S'il s'exécute à partir d'une fenêtre de commande PowerShell, il ne ferme pas la fenêtre.
Joshua Nurczyk
14
La réponse de New Guy est beaucoup plus approfondie et mérite d'être marquée comme acceptée.
Jim Aho
585

Je me rends compte que c'est un ancien post mais je me retrouve à revenir sur ce sujet car c'est l'un des meilleurs résultats de recherche lorsque vous recherchez ce sujet. Cependant, je laisse toujours plus confus que quand je suis venu en raison des informations contradictoires. En fin de compte, je dois toujours effectuer mes propres tests pour le comprendre. Cette fois, je vais donc publier mes résultats.

TL; DR La plupart des gens voudront utiliser Exitpour terminer un script en cours d'exécution. Cependant, si votre script déclare simplement des fonctions à utiliser ultérieurement dans un shell, alors vous voudrez les utiliser Returndans les définitions desdites fonctions.

Sortie vs retour vs pause

  • Quitter: cela "quittera" le contexte en cours d'exécution. Si vous appelez cette commande à partir d'un script, elle quittera le script. Si vous appelez cette commande à partir du shell, elle quittera le shell.

    Si une fonction appelle la commande Exit, elle quittera le contexte dans lequel elle s'exécute. Ainsi, si cette fonction n'est appelée qu'à partir d'un script en cours d'exécution, elle quittera ce script. Cependant, si votre script déclare simplement la fonction afin qu'elle puisse être utilisée à partir du shell actuel et que vous exécutez cette fonction à partir du shell, il quittera le shell car le shell est le contexte dans lequel la fonction contenant la Exitcommande s'exécute.

    Remarque: Par défaut, si vous cliquez avec le bouton droit sur un script pour l'exécuter dans PowerShell, une fois le script exécuté, PowerShell se fermera automatiquement. Cela n'a rien à voir avec la Exitcommande ou quoi que ce soit d'autre dans votre script. Il s'agit simplement d'un comportement PowerShell par défaut pour les scripts exécutés à l'aide de cette méthode spécifique d'exécution d'un script. Il en va de même pour les fichiers batch et la fenêtre de ligne de commande.

  • Revenir: Cela reviendra au point d'appel précédent. Si vous appelez cette commande à partir d'un script (en dehors de toute fonction), elle reviendra au shell. Si vous appelez cette commande à partir du shell, elle reviendra au shell (qui est le point d'appel précédent pour une seule commande exécutée à partir du shell). Si vous appelez cette commande à partir d'une fonction, elle retournera à l'endroit où la fonction a été appelée.

    L'exécution de toutes les commandes après le point d'appel auquel il est renvoyé se poursuivra à partir de ce point. Si un script est appelé à partir du shell et qu'il contient la Returncommande en dehors de toute fonction, alors quand il revient au shell, il n'y a plus de commandes à exécuter, rendant ainsi un Returnutilisé de cette manière essentiellement identique à Exit.

  • Break: Cela va sortir des boucles et changer les boîtiers. Si vous appelez cette commande alors qu'elle n'est pas dans une boucle ou un commutateur, elle sortira du script. Si vous appelez à l' Breakintérieur d'une boucle imbriquée dans une boucle, elle ne sortira que de la boucle dans laquelle elle a été appelée.

    Il y a aussi une fonctionnalité intéressante Breakoù vous pouvez préfixer une boucle avec une étiquette et ensuite vous pouvez sortir de cette boucle étiquetée même si la Breakcommande est appelée dans plusieurs groupes imbriqués dans cette boucle étiquetée.

    While ($true) {
        # Code here will run
    
        :myLabel While ($true) {
            # Code here will run
    
            While ($true) {
                # Code here will run
    
                While ($true) {
                    # Code here will run
                    Break myLabel
                    # Code here will not run
                }
    
                # Code here will not run
            }
    
            # Code here will not run
        }
    
        # Code here will run
    }
Nouveau gars
la source
39
A noter également que Exitpeut prendre un code retour comme paramètre (par défaut à 0) - par exemple Exit 3.
aucuparia
2
Je suis d'accord, c'est une bien meilleure réponse. La «pause» peut avoir des conséquences inattendues.
iagomartinez
Je ne suis pas sûr que votre commentaire sur "Quitter" soit complètement correct, bien que ce soit une excellente réponse dans l'ensemble. La sortie semble entraîner la fermeture de l'ISE d'une manière que rien d'autre ne semble faire. Quitter simplement le contexte (par exemple, le script se termine) ne fait pas cela.
Bill K
1
@BillK Effectivement. J'ai mis à jour la réponse. Lorsque j'ai écrit cela pour la première fois, je me souviens n'avoir trouvé aucune documentation officielle sur Exit. J'ai ensuite fait un Get-Command Exitet Get-Alias Exitsans résultat. J'ai ensuite cherché à voir s'il s'agissait d'un mot-clé et je n'ai trouvé aucune documentation officielle à ce sujet. Mais en y regardant maintenant, je ne sais pas comment j'en suis arrivé à cette conclusion. Il s'agit clairement d'un mot clé ( technet.microsoft.com/en-us/library/hh847744.aspx ). Peut-être parce qu'Exit est l'un des seuls mots clés à ne pas avoir sa propre rubrique d'aide about_ et que la liste des rubriques dans la barre latérale gauche ne l'a donc pas inclus.
New Guy
7
Et Throw?
JDC
80

Exitquittera également PowerShell. Si vous souhaitez "sortir" de la fonction ou du script en cours, utilisez Break:)

If ($Breakout -eq $true)
{
     Write-Host "Break Out!"
     Break
}
ElseIf ($Breakout -eq $false)
{
     Write-Host "No Breakout for you!"
}
Else
{
    Write-Host "Breakout wasn't defined..."
}
EverydayNerd
la source
5
Veuillez ne pas utiliser breaklorsque vous voulez simplement sortir de la fonction actuelle ... les scripts d'appel peuvent également être perturbés!
DannyMeister
49

Write-Error est pour les erreurs qui ne se terminent pas et throw est pour les erreurs qui se terminent

L'applet de commande Write-Error déclare une erreur sans fin. Par défaut, les erreurs sont envoyées dans le flux d'erreurs au programme hôte à afficher, avec la sortie.

Les erreurs qui ne se terminent pas écrivent une erreur dans le flux d'erreurs, mais elles n'arrêtent pas le traitement des commandes. Si une erreur sans fin est déclarée sur un élément d'une collection d'éléments d'entrée, la commande continue de traiter les autres éléments de la collection.

Pour déclarer une erreur de fin, utilisez le mot clé Throw. Pour plus d'informations, consultez about_Throw ( http://go.microsoft.com/fwlink/?LinkID=145153 ).

Greg Bray
la source
4
Cela semble la façon la plus correcte de terminer une activité avec une erreur. Il délègue à l'appelant de tenter de gérer l'erreur, ce qui est bien mieux que de simplement tenter de mettre fin brusquement.
Paul Turner
Pour moi, au moins dans les fonctions du module, lancez des sorties mais ne définissez pas de code de sortie. Cela a été exécuté via CLI par exemple powershell -command "& module-function ...". J'avais besoin de convertir ces fonctions pour les lancer en un catch-wrapping et sortir de ce catch afin de réellement sortir un code de sortie d'erreur.
Josh
2
N'oubliez pas $PSCmdlet.ThrowTerminatingError()pour les cas où throw ne peut tout simplement pas faire le travail (problème connu sans aucune erreur de terminaison throw)
Djarid
33

Met fin à ce processus et donne au système d'exploitation sous-jacent le code de sortie spécifié.

https://msdn.microsoft.com/en-us/library/system.environment.exit%28v=vs.110%29.aspx

[Environment]::Exit(1)

Cela vous permettra de quitter avec un code de sortie spécifique, qui peut être récupéré auprès de l'appelant.

gabriwinter
la source
3
Dans PowerShell, vous pouvez simplement utiliser la sortie intégrée pour cela, par exemple Exit 1.
Jonas
3
La sortie intégrée ne fonctionnera pas toujours comme prévu. Essayez ceci dans powershell: "Exit 5"> test1.ps1 powershell.exe. \ Test1.ps1 $ lastexitcode "[Environment] :: Exit (5)"> test2.ps1 powershell.exe. \ Test2.ps1 $ lastexitcode
gabriwinter
1
[Environment]::Exit(1)a pour effet secondaire de quitter ma fenêtre PowerShell lorsque je l'invoque dans un script, alors que l'utilisation exitne semble pas le faire.
Josh Desmond
25

Je pense que vous cherchez au Returnlieu de Break. La rupture est généralement utilisée pour les boucles et uniquement les ruptures du bloc de code le plus interne. Utilisez Retour pour quitter une fonction ou un script.

Rob
la source
7
Ce n'est pas correct - l'OP demande spécifiquement de quitter un script depuis une fonction . Returnreviendra simplement de la fonction, pas du script. ( Returnau niveau supérieur d'un script mettra fin au script, mais ce n'était pas la question.)
Michael Sorens
1
cette «réponse» commentait-elle réellement la réponse EverydayNerd?
tkokasih
22

Lancer une exception sera utile, surtout si vous souhaitez clarifier la raison de l'erreur:

throw "Error Message"

Cela générera une erreur de terminaison.

Amr Bahaa
la source
4
Je ne pense pas que cela ajoute plus que la réponse de Greg Bray près d'un an plus tôt stackoverflow.com/a/20556550/695671
Jason S
12

Peut-être vaut-il mieux utiliser "trap". Un déroutement PowerShell spécifie un bloc de code à exécuter en cas d'arrêt ou d'erreur. Type

Get-Help about_trap

pour en savoir plus sur l'instruction trap.

fpschultze
la source
10

Je trouve par hasard que (par exemple simplement , où l'étiquette n'existe pas ) semble sortir du script entier (même à l' intérieur d' une fonction) et maintient l'hôte vivant. De cette façon, vous pouvez créer une fonction qui rompt le script de n'importe où (par exemple une boucle récursive) sans connaître la portée actuelle (et créer des étiquettes):Break <UnknownLabel>Break ScriptScript

Function Quit($Text) {
    Write-Host "Quiting because: " $Text
    Break Script
} 
le fer
la source
1
Votre réponse est vraie, mais sachez que cela peut causer des problèmes aux appelants de votre script s'ils ne sont pas d'accord avec votre désir de quitter l'intégralité du script: stackoverflow.com/questions/45746588/…
DannyMeister
5

Je l'ai utilisé pour une nouvelle exécution d'un programme. Je ne sais pas si cela aiderait, mais c'est une simple instruction if ne nécessitant que deux entrées différentes. Cela a fonctionné en PowerShell pour moi.

$rerun = Read-Host "Rerun report (y/n)?"

if($rerun -eq "y") { Show-MemoryReport }
if($rerun -eq "n") { Exit }

Je ne sais pas si cela aide, mais je pense que ce serait dans le sens de terminer un programme après l'avoir exécuté. Cependant, dans ce cas, chaque entrée définie nécessite une sortie répertoriée et catégorisée. Vous pouvez également demander à la sortie d'appeler une nouvelle ligne d'invite et de terminer le programme de cette façon.

Michael Meli
la source