Terminare uno script in PowerShell


394

Ho cercato un modo per terminare uno script di PowerShell (PS1) quando si verifica un errore irreversibile all'interno di una funzione. Per esempio:

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

Certo che non esiste $host.Exit(). C'è $host.SetShouldExit(), ma questo in realtà chiude la finestra della console, che non è quello che voglio. Ciò di cui ho bisogno è qualcosa di equivalente a quello di Python sys.exit()che fermerà semplicemente l'esecuzione dello script corrente senza ulteriori indugi.

Modifica: Sì, è solo exit. Duh.


8
Se vuoi evitare di chiudere la finestra di PowerShell o ISE nel mio caso; usa invece "return". Termina solo il contesto corrente corrente. "New guy" spiega a fondo tutte le opzioni a fini educativi; potresti prendere in considerazione la possibilità di modificare la risposta accettata (attualmente ha più voti positivi) per i futuri utenti StackOverflow. Ti permetterà anche di eseguire il debug dello script.
ZaxLofful,

Risposte:


389

Dovresti usare la exitparola chiave .


15
Santa merda, se non fossi stato così preso dal tentativo di capire come fare queste cose in modo intelligente, probabilmente avrei provato che all'inizio e ho capito che funziona :) Grazie.
kprobst,

118
Come è questa la risposta accettata? In particolare "chiude la finestra della console" che il richiedente ha detto "che non è quello che voglio".
claudekennilol,

3
@claudekennilol Solo chi pone la domanda può accettare una risposta. O hanno perso il fatto che l'uscita dovrebbe chiudere la finestra, oppure hanno cambiato idea e lo hanno ritenuto accettabile per il loro scopo.
Iszi,

3
Non chiude la finestra della console in v3 o v4, che uso. Bene, lo farà se esegui lo script da explorer, ma non importa come finisci lo script lo farà. Se eseguito da una finestra di comando di PowerShell, non chiude la finestra.
Joshua Nurczyk,

14
La risposta di New Guy è molto più approfondita e merita di essere contrassegnata come accettata.
Jim Aho,

585

Mi rendo conto che questo è un vecchio post, ma mi ritrovo a tornare su questa discussione in quanto è uno dei migliori risultati di ricerca durante la ricerca di questo argomento. Tuttavia, lascio sempre più confuso rispetto a quando sono venuto a causa di informazioni contrastanti. Alla fine devo sempre eseguire i miei test per capirlo. Quindi questa volta posterò i miei risultati.

TL; DR Molte persone vorranno usare Exitper terminare uno script in esecuzione. Tuttavia, se il tuo script sta semplicemente dichiarando che le funzioni verranno successivamente utilizzate in una shell, ti consigliamo di utilizzarle Returnnelle definizioni di tali funzioni.

Exit vs Return vs Break

  • Esci: questo "esce" dal contesto attualmente in esecuzione. Se si chiama questo comando da uno script, uscirà dallo script. Se chiamate questo comando dalla shell, uscirà dalla shell.

    Se una funzione chiama il comando Exit, uscirà dal contesto in cui è in esecuzione. Quindi, se quella funzione viene chiamata solo da uno script in esecuzione, uscirà da quello script. Tuttavia, se il tuo script dichiara semplicemente la funzione in modo che possa essere utilizzata dalla shell corrente ed esegui quella funzione dalla shell, uscirà dalla shell perché la shell è il contesto in cui Exitè in esecuzione la funzione che contian il comando.

    Nota: per impostazione predefinita, se si fa clic con il pulsante destro del mouse su uno script per eseguirlo in PowerShell, al termine dell'esecuzione dello script, PowerShell si chiuderà automaticamente. Questo non ha nulla a che fare con il Exitcomando o qualsiasi altra cosa nel tuo script. È solo un comportamento predefinito di PowerShell per gli script eseguiti utilizzando questo metodo specifico di esecuzione di uno script. Lo stesso vale per i file batch e la finestra della riga di comando.

  • Ritorno: questo ritornerà al punto di chiamata precedente. Se si chiama questo comando da uno script (al di fuori di qualsiasi funzione), tornerà alla shell. Se chiamate questo comando dalla shell tornerà alla shell (che è il punto di chiamata precedente per un singolo comando eseguito dalla shell). Se si chiama questo comando da una funzione, tornerà da dove mai è stata chiamata la funzione.

    L'esecuzione di qualsiasi comando dopo il punto di chiamata a cui viene restituito continuerà da quel punto. Se uno script viene chiamato dalla shell e contiene il Returncomando al di fuori di qualsiasi funzione, allora quando ritorna alla shell non ci sono più comandi da eseguire, facendo un Returnuso in questo modo essenzialmente uguale a Exit.

  • Interruzione: questa operazione interromperà i loop e cambierà caso. Se si chiama questo comando mentre non si è in un ciclo o si cambia caso, uscirà dallo script. Se si chiama Breakall'interno di un loop nidificato all'interno di un loop, si interromperà solo dal loop nel quale è stato chiamato.

    C'è anche una caratteristica interessante di Breakdove è possibile anteporre un ciclo con un'etichetta e quindi è possibile uscire da quel ciclo etichettato anche se il Breakcomando viene chiamato all'interno di più gruppi nidificati all'interno di quel ciclo etichettato.

    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
    }

39
Vale anche la pena notare che Exitpuò prendere un codice di ritorno come parametro (il valore predefinito è 0) - ad es Exit 3.
aucuparia,

2
Sono d'accordo, questa è una risposta molto migliore. La "rottura" può avere conseguenze non intenzionali.
iagomartinez,

Non sono sicuro che il tuo commento su "Exit" sia del tutto corretto, sebbene nel complesso sia un'ottima risposta. L'uscita sembra causare la chiusura dell'ISE in un modo che nient'altro sembra fare. La semplice uscita dal contesto (ad esempio il completamento dello script) non lo fa.
Bill K,

1
@BillK In effetti. Ho aggiornato la risposta. Quando l'ho scritto per la prima volta, ricordo di non aver trovato alcuna documentazione ufficiale su Exit. Poi ho fatto un Get-Command Exite Get-Alias Exitsenza risultati. Ho quindi cercato di vedere se si trattava di una parola chiave e non ho trovato alcuna documentazione ufficiale su di essa. Guardandolo ora, tuttavia, non so come sono arrivato a questa conclusione. Chiaramente è una parola chiave ( technet.microsoft.com/en-us/library/hh847744.aspx ). Forse perché Exit è una delle uniche parole chiave che non ha il proprio argomento about_ help e quindi l'elenco degli argomenti nella barra laterale di sinistra non lo include.
New Guy

6
Che dire di Throw?
JDC,

80

Exituscirà anche da PowerShell. Se desideri "uscire" solo dalla funzione o dallo script corrente, usa 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..."
}

5
Si prega di non utilizzare breakquando si desidera semplicemente uscire dalla funzione corrente ... Anche la chiamata di script può essere interrotta!
DannyMeister,

49

Write-Error è per errori non terminanti e buttare è per errori di terminazione

Il cmdlet Error-Write dichiara un errore non terminante. Per impostazione predefinita, gli errori vengono inviati nel flusso di errori al programma host da visualizzare, insieme all'output.

Gli errori non terminanti scrivono un errore nel flusso di errori, ma non interrompono l'elaborazione dei comandi. Se viene dichiarato un errore non terminante su un elemento in una raccolta di elementi di input, il comando continua a elaborare gli altri elementi nella raccolta.

Per dichiarare un errore di terminazione, utilizzare la parola chiave Throw. Per ulteriori informazioni, vedere about_Throw ( http://go.microsoft.com/fwlink/?LinkID=145153 ).


4
Questo sembra il modo più corretto per terminare un'attività con un errore. Delega al chiamante il tentativo di gestire l'errore, il che è molto meglio del semplice tentativo di terminare bruscamente.
Paul Turner,

Per me, almeno nelle funzioni del modulo, lanciare le uscite ma non impostare un codice di uscita. Questo è stato eseguito tramite CLI ad es powershell -command "& module-function ...". Avevo bisogno di convertire quelle funzioni da lanciare in un wrapping try-catch e uscire da quel wrapping catch per poter effettivamente generare un codice di uscita dell'errore.
Josh

2
Non dimenticare $PSCmdlet.ThrowTerminatingError()per quei casi in cui il lancio non riesce a portare a termine il lavoro (problema noto senza errori di chiusura throw)
Djarid

33

Termina questo processo e fornisce al sistema operativo sottostante il codice di uscita specificato.

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

[Environment]::Exit(1)

Ciò ti consentirà di uscire con un codice di uscita specifico, che può essere prelevato dal chiamante.


3
In PowerShell, puoi semplicemente usare l'uscita integrata per questo, ad es Exit 1.
Jonas,

3
l'uscita integrata non funzionerà sempre come previsto. Prova questo in powershell: "Exit 5"> test1.ps1 powershell.exe. \ Test1.ps1 $ lastexitcode "[Ambiente] :: Exit (5)"> test2.ps1 powershell.exe. \ Test2.ps1 $ lastexitcode
gabriwinter

1
[Environment]::Exit(1)ha l'effetto collaterale di uscire dalla mia finestra di PowerShell quando la invoco in uno script, dove l'utilizzo exitnon sembra farlo.
Josh Desmond,

25

Penso che tu stia cercando Returninvece di Break. L'interruzione viene in genere utilizzata per i loop e solo interruzioni dal blocco di codice più interno. Utilizzare Return per uscire da una funzione o da uno script.


7
Ciò non è corretto: l'OP chiede specificamente di uscire da uno script all'interno di una funzione . Returntornerà semplicemente dalla funzione, non dallo script. ( Returnal livello più alto di una sceneggiatura la terminerà, ma non era questa la domanda.)
Michael Sorens,

1
questa "risposta" era in realtà un commento sulla risposta di EverydayNerd?
Bangkok

22

Generare un'eccezione andrà bene soprattutto se si desidera chiarire il motivo dell'errore:

throw "Error Message"

Ciò genererà un errore di chiusura.


3
Non credo che ciò aggiunga altro che la risposta di Greg Bray quasi un anno prima stackoverflow.com/a/20556550/695671
Jason S

12

Potrebbe essere meglio usare "trap". Una trap di PowerShell specifica un codeblock da eseguire in caso di interruzione o errore. genere

Get-Help about_trap

per saperne di più sull'istruzione trap


10

Ho scoperto per coincidenza che (ad es. Semplicemente , dove l'etichetta non esiste ) sembra uscire dall'intero script (anche dall'interno di una funzione) e mantiene in vita l'host. In questo modo è possibile creare una funzione che interrompe lo script da qualsiasi luogo (ad esempio un ciclo ricorsivo) senza conoscere l'ambito corrente (e la creazione di etichette):Break <UnknownLabel>Break ScriptScript

Function Quit($Text) {
    Write-Host "Quiting because: " $Text
    Break Script
} 

1
La tua risposta è vero, ma essere consapevoli questo può causare problemi per i chiamanti dello script, se non sono d'accordo con il vostro desiderio di uscire l'intero script: stackoverflow.com/questions/45746588/...
DannyMeister

5

L'ho usato per una riesecuzione di un programma. Non so se sarebbe di aiuto, ma è una semplice dichiarazione if che richiede solo due voci diverse. Ha funzionato in PowerShell per me.

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

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

Non so se questo aiuta, ma credo che questo sarebbe sulla falsariga di terminare un programma dopo averlo eseguito. Tuttavia, in questo caso, ogni input definito richiede un output elencato e classificato. Potresti anche avere l'uscita che richiama una nuova riga di prompt e termina il programma in quel modo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.