PowerShell Script 結束執行的正確姿勢
1 |
在 PowerShell 中想提前結束程式有好幾種寫法,例如 return、exit,之前沒認真比過差異,胡亂用踩了坑,特整理筆記備忘。
先用以下 Test-ExitScript.ps1 程式示範,依傳入參數模擬四種提前結束 Script 的做法 - return、break、exit 及 [Environment]::Exit(),程式最後有個 Write-Host 'You should not see this'
,正常狀況不會顯示,用以驗證程式已提前中止。
param([string]$method = 'return')
Write-Host "Terminating script with '$method'"
if ($method -eq 'nothing') {
# do nothing
}
elseif ($method -eq 'return') {
return
}
elseif ($method -eq 'break') {
break
}
elseif ($method -eq 'exit') {
exit
}
elseif ($method -eq 'dos-exit') {
[Environment]::Exit(255)
}
else {
throw "Unkown method - $method"
}
Write-Host 'You should not see this'
第一組測試用 powershell .\\Test-ExitScript.ps1 xxxx
方式執行,四種方法都正確提前結束程式。
但如果使用 PowerShell 主控台 或先執行 PowerShell.exe 進入互動模式,結果則有點不同。如下圖,我在 Cmder 先輸入 powershell 進入互動模式,接著呼叫 .\Test-ExitScript.ps1 xxxx 進行測試,return、break、exit 都正常,但 [Environment]::Exit() 會結束 PowerShell 互動模式回到 Cmder:
有趣的是,如果把同樣程式包成 Function 裡,結果又會不相同。
function TestExit($method) {
Write-Host "Terminating script with '$method'"
if ($method -eq 'nothing') {
# do nothing
}
elseif ($method -eq 'return') {
return
}
elseif ($method -eq 'break') {
break
}
elseif ($method -eq 'exit') {
exit
}
elseif ($method -eq 'dos-exit') {
[Environment]::Exit(255)
}
else {
throw "Unkown method - $method"
}
Write-Host 'You should not see this'
}
實測如下,先執行 powershell (1) 進入互動模式,用 . .\Test-ExitScriptInFunc.ps1 載入 function TestExit($method) 函式 (2),接著呼叫 TestExit xxxx 測試不同退出方法 (3),發現 exit (4) 跟 [Environment]::Exit() 都會導致 PowerShell 互動環境結束:
【結論】
由結果來看,若以排程執行單一 .ps1,四個方法都可提前結束執行,但 break 原本用於跳出 loop、while,移作他用易造成別人困惑,不推。exit 關鍵字 及 [Environment]::Exit() 搭配 Exit Code,可供 .BAT 判斷 %ERRORLEVEL% 做不同處理,有額外的應用場合。
但在 PowerShell 互動模式執行 .ps1 時,[Environment]::Exit() 有中止 PowerShell 互動環境的副作用。
如果要在 function 結束執行,建議乖乖用 return 就好,exit 跟 [Environment]::Exit() 都會強迫關閉 PowerShell 環境。我這次踩到的雷便是發生將 .ps1 包成 PowerShell 模組的過程,原本 .ps1 中用 exit 相安無事,改成 function 後安裝成模組,呼叫函式時發現 PowerShell 主控台會閃退,經過一番研究才搞懂是怎麼一回事。
大家如果有在 .ps1 使用 exit,改寫成函式或模組時,要留意這個小坑。
Difference among exit, break, return and [Environment]::Exit() in PowerShell.
Comments
# by Huang
function搭配return,結束搭配exit應該是不會搞錯