HOWTO · PowerShell
Come terminare uno script in Windows PowerShell
Scopri quando usare exit, return, throw, break, continue o Stop-Process per fermare l'ambito corretto e restituire un codice di uscita PowerShell affidabile.
In questa pagina
Terminare uno script PowerShell non è una singola operazione. L’istruzione corretta dipende da ciò che deve fermarsi: l’intero processo dello script, la funzione corrente, un’iterazione oppure un altro processo del sistema operativo.
| Obiettivo | Istruzione |
|---|---|
| Terminare lo script principale e comunicare uno stato | exit <codice> |
| Uscire da una funzione, uno script o uno scriptblock | return |
| Segnalare un errore intercettabile dal chiamante | throw |
Uscire da un ciclo o da switch |
break |
Passare all’elemento successivo del ciclo o di switch |
continue |
| Terminare un altro processo locale | Stop-Process |
Terminare uno script PowerShell con exit
exit termina uno script o un’istanza di PowerShell. Un intero facoltativo diventa il codice di uscita del processo: per convenzione, 0 indica il successo e un valore diverso da zero indica un errore. Documenta ogni codice di errore affinché attività pianificate, processi CI e programmi chiamanti possano reagire correttamente.
Salva questo script di ingresso come 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
Eseguilo come processo figlio da un’altra sessione PowerShell, quindi controlla lo stato:
powershell.exe -NoProfile -File .\Check-Config.ps1 -Path .\missing.json
$LASTEXITCODE
L’ultimo comando visualizza 2. Con PowerShell 7 usa pwsh al posto di powershell.exe. PowerShell espone lo stato del processo figlio tramite $LASTEXITCODE; un chiamante cmd.exe lo legge da %ERRORLEVEL%.
Riserva exit al confine dello script principale. Se una funzione riutilizzabile chiama exit, può chiudere una sessione interattiva, un test runner o un altro host. È preferibile che le funzioni restituiscano dati o generino errori e che solo lo script di ingresso converta il risultato in un codice di uscita.
Uscire dall’ambito corrente con return
return esce dalla funzione, dallo script o dallo scriptblock corrente. Da solo non imposta un codice di uscita del processo.
function Get-ConfigText {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
return $null
}
Get-Content -LiteralPath $Path -Raw
}
In una normale funzione PowerShell, ogni valore non acquisito del flusso di successo diventa parte dell’output, non soltanto l’espressione dopo return. Per i messaggi diagnostici usa Write-Verbose o un altro flusso appropriato invece di emettere stringhe aggiuntive con Write-Output.
Fermarsi con un errore intercettabile usando throw
throw crea per impostazione predefinita un errore che termina lo script e risale lo stack di chiamate finché un blocco catch o un’istruzione trap non lo gestisce. Usalo quando una funzione non può produrre un risultato valido e il chiamante deve decidere come recuperare.
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
}
Questo modello separa le responsabilità: la funzione descrive l’errore con throw, mentre lo script di ingresso lo intercetta e sceglie il codice pubblico. Non tutti gli errori dei cmdlet raggiungono automaticamente catch; aggiungi -ErrorAction Stop a un errore non terminante quando deve essere gestito lì.
Usare break e continue solo nei blocchi di controllo
break esce dal ciclo o dallo switch più vicino. continue salta il resto dell’iterazione corrente e avvia quella successiva.
foreach ($name in 'alpha', '', 'beta', 'stop', 'omega') {
if ([string]::IsNullOrWhiteSpace($name)) {
continue
}
if ($name -eq 'stop') {
break
}
Write-Output $name
}
Output:
alpha
beta
Non sono comandi generici per terminare uno script. Fuori da un ciclo, da switch o da trap, PowerShell può cercare nello stack di chiamate un costrutto contenitore e terminare il runspace corrente se non ne trova uno.
Terminare un altro processo con Stop-Process
Stop-Process agisce su un processo distinto nel computer locale; non significa “fermare questo script”. Verifica prima una selezione ampia con -WhatIf:
Get-Process -Name notepad -ErrorAction SilentlyContinue |
Stop-Process -WhatIf
Rimuovi -WhatIf solo dopo aver confermato i processi scelti. Preferisci un oggetto processo noto o un PID quando un nome può corrispondere a più processi. Per arrestare il processo di un altro utente può essere necessaria anche una sessione PowerShell con privilegi elevati.
Conservare i codici di uscita dei programmi nativi
$? indica se l’ultimo comando PowerShell è riuscito, mentre $LASTEXITCODE contiene il codice di uscita dell’ultimo programma nativo. Salva subito il valore, perché il comando nativo successivo può sovrascriverlo.
git status --porcelain
$gitCode = $LASTEXITCODE
if ($gitCode -ne 0) {
Write-Error "git failed with exit code $gitCode"
exit $gitCode
}
Usa return o throw nella logica riutilizzabile e riserva exit <codice> al confine dello script principale. In questo modo l’output delle funzioni, il flusso di controllo e lo stato del processo rimangono separati.
Preservare la pulizia e distinguere l’annullamento
Mantieni la pulizia in finally, non dopo una riga che può arrestare l’elaborazione. Secondo la documentazione sulle parole chiave PowerShell, finally viene eseguito se il lavoro in try riesce, se un errore raggiunge catch, se viene chiamato exit o se Ctrl+C interrompe lo script; usalo per rilasciare uno stream, un blocco o un file temporaneo.
$stream = $null
try {
$stream = [System.IO.File]::OpenRead($Path)
# Process the stream.
}
finally {
if ($null -ne $stream) {
$stream.Dispose()
}
}
Lascia che il codice riutilizzabile usi throw o return fino allo script di ingresso, così pulizia e stato del processo restano in un punto visibile. Ctrl+C, un processo in background arrestato e un input non valido sono eventi diversi: decidi e documenta se ciascuno è un annullamento, un errore di convalida o un altro stato a cui chiamante o pianificatore devono reagire. Non ridurli silenziosamente a un errore generico. Arrestare un altro processo è diverso; preferisci la chiusura normale dell’applicazione. Stop-Process -Force può impedire la pulizia di file o stato; usalo solo conoscendone la conseguenza.
Mantenere script figli e host nell’ambito previsto
L’operatore di chiamata esegue uno script figlio nel proprio ambito; il dot-sourcing lo esegue nell’ambito corrente e importa funzioni e variabili. Usa il dot-sourcing solo quando importare definizioni è intenzionale.
# Run the child in its own script scope.
& .\Child.ps1
# Import definitions into the current scope.
. .\Functions.ps1
Un exit nel codice riutilizzabile può chiudere una sessione interattiva, un runner di test o un altro host. Un figlio avviato con powershell.exe -File o pwsh -File restituisce il controllo al chiamante; una console interattiva può chiudere la sessione. Runspace incorporati ed editor possono comportarsi diversamente. Prova il comando di produzione reale, compresi -File rispetto a -Command, profili, quoting, output e stato separatamente.
Raccomandazione
Riserva exit <codice> al confine di livello superiore, return all’ambito corrente, throw a un errore gestibile, break e continue al relativo ciclo o switch, e Stop-Process a un processo locale distinto. Funzioni che restituiscono dati o generano errori restano riutilizzabili; un piccolo script di ingresso può tradurre il risultato per shell, pianificatore, CI o wrapper.