HOWTO · PowerShell
Windows PowerShellでスクリプトを終了する方法
PowerShell で exit、return、throw、break、continue、Stop-Process を使い分け、適切なスコープを終了して終了コードを返す方法を解説します。
このページの内容
PowerShell スクリプトの「終了」には複数の意味があります。スクリプトのプロセス全体、現在の関数、ループの反復、別の OS プロセスのどれを止めるかによって、使用するステートメントが異なります。
| 目的 | 使用するもの |
|---|---|
| 最上位スクリプトを終了して状態を返す | exit <コード> |
| 関数、スクリプト、またはスクリプトブロックを抜ける | return |
| 呼び出し元が捕捉できるエラーを通知する | throw |
ループまたは switch を抜ける |
break |
次のループまたは switch の要素へ進む |
continue |
| 別のローカルプロセスを終了する | Stop-Process |
exit で PowerShell スクリプトを終了する
exit はスクリプトまたは PowerShell インスタンスを終了します。省略可能な整数がプロセスの終了コードになります。慣例では 0 が成功、0 以外が失敗です。タスクスケジューラ、CI、ラッパープログラムが正しく判断できるように、各エラーコードの意味を文書化してください。
次のエントリースクリプトを 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
別の PowerShell セッションから子プロセスとして実行し、状態を確認します。
powershell.exe -NoProfile -File .\Check-Config.ps1 -Path .\missing.json
$LASTEXITCODE
最後のコマンドは 2 を表示します。PowerShell 7 では powershell.exe の代わりに pwsh を使用します。PowerShell の呼び出し元は $LASTEXITCODE から子プロセスの状態を取得でき、cmd.exe では %ERRORLEVEL% を使用します。
exit は最上位スクリプトの境界に限定するのが安全です。再利用する関数内で呼ぶと、対話セッション、テストランナー、または呼び出し元ホストまで閉じる可能性があります。関数はデータを返すかエラーをスローし、エントリースクリプトだけが結果を終了コードへ変換する構成にします。
return で現在のスコープを抜ける
return は現在の関数、スクリプト、またはスクリプトブロックを抜けます。それ自体がプロセスの終了コードを設定するわけではありません。
function Get-ConfigText {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path -PathType Leaf)) {
return $null
}
Get-Content -LiteralPath $Path -Raw
}
通常の PowerShell 関数では、return の後の式だけでなく、捕捉されていない成功ストリームの値がすべて出力になります。診断メッセージには余分な文字列を Write-Output で出すのではなく、Write-Verbose など適切なストリームを使用してください。
throw で捕捉可能なエラーを通知する
throw は既定でスクリプト終了エラーを生成し、catch ブロックまたは trap が処理するまで呼び出しスタックを巻き戻します。関数が有効な結果を返せず、回復方法を呼び出し元に判断させる場合に使用します。
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
}
このパターンでは責務が分かれます。関数は throw で失敗理由を伝え、エントリースクリプトが捕捉して公開する終了コードを決めます。すべての cmdlet エラーが自動的に catch へ届くわけではありません。非終了エラーをそこで処理する必要がある場合は -ErrorAction Stop を指定します。
break と continue は制御ブロック内だけで使う
break は最も近いループまたは switch を終了します。continue は現在の反復の残りを飛ばして次へ進みます。
foreach ($name in 'alpha', '', 'beta', 'stop', 'omega') {
if ([string]::IsNullOrWhiteSpace($name)) {
continue
}
if ($name -eq 'stop') {
break
}
Write-Output $name
}
出力:
alpha
beta
これらは汎用のスクリプト終了コマンドではありません。ループ、switch、trap の外で使うと、PowerShell は呼び出しスタック上の制御構造を探し、見つからなければ現在のランスペースを終了することがあります。
Stop-Process で別のプロセスを終了する
Stop-Process はローカルコンピューター上の別プロセスを対象とし、現在のスクリプトを終了するものではありません。広い条件を使う前に -WhatIf で対象を確認します。
Get-Process -Name notepad -ErrorAction SilentlyContinue |
Stop-Process -WhatIf
対象を確認してから -WhatIf を外してください。同じ名前のプロセスが複数ある場合は、既知のプロセスオブジェクトまたは PID を優先します。別ユーザーが所有するプロセスの停止には、管理者権限の PowerShell セッションが必要な場合もあります。
ネイティブプログラムの終了コードを保持する
$? は直前の PowerShell コマンドが成功したかを示します。一方、$LASTEXITCODE は直前のネイティブプログラムの終了コードを保持します。次のネイティブコマンドで上書きされるため、すぐに保存してください。
git status --porcelain
$gitCode = $LASTEXITCODE
if ($gitCode -ne 0) {
Write-Error "git failed with exit code $gitCode"
exit $gitCode
}
再利用するロジックでは return または throw を使い、exit <コード> は最上位スクリプトに限定します。これにより、関数の出力、制御フロー、OS のプロセス状態を混同せずに扱えます。
クリーンアップを保持し、キャンセルと区別する
クリーンアップは、処理を止める可能性がある行の後ではなく finally に置きます。PowerShell の言語キーワードのドキュメントによれば、finally は try が成功した場合、エラーが catch に届いた場合、exit が呼ばれた場合、または Ctrl+C がスクリプトを中断した場合にも実行されます。そのため、ストリーム、ロック、一時ファイルを解放する場所として適しています。
$stream = $null
try {
$stream = [System.IO.File]::OpenRead($Path)
# Process the stream.
}
finally {
if ($null -ne $stream) {
$stream.Dispose()
}
}
再利用するコードは、途中で exit を呼ぶのではなく、エントリースクリプトへ throw または return します。これにより、クリーンアップ、診断、終了状態を一か所で決められます。Ctrl+C、停止されたジョブ、無効な入力は別のイベントです。それぞれをキャンセル、検証失敗、または呼び出し元・スケジューラが処理すべき別の状態のどれにするかを決め、文書化してください。これらを黙って一般的な失敗へまとめないでください。別プロセスを止めることはさらに別であり、通常の終了手段を優先します。Stop-Process -Force がファイルや状態のクリーンアップを妨げる影響を理解した場合だけ使用してください。
子スクリプトとホストを意図したスコープに保つ
呼び出し演算子は子スクリプトを独自のスクリプトスコープで実行します。ドットソーシングは現在のスコープで実行し、関数と変数を取り込みます。定義の取り込みが目的の場合にだけ使用します。
# Run the child in its own script scope.
& .\Child.ps1
# Import definitions into the current scope.
. .\Functions.ps1
再利用コードの exit は return より強く、対話セッション、テストランナー、別のホストを閉じることがあります。powershell.exe -File または pwsh -File で開始した子プロセスは呼び出し元へ制御を返しますが、対話コンソールは現在のセッションを閉じることがあります。埋め込み Runspace やエディターは異なる場合があります。-File と -Command、プロファイル、引用符、出力、終了状態を含め、実運用のコマンドラインを個別に確認してください。
推奨事項
最上位スクリプトの終了には exit <コード>、現在のスコープを抜けるには return、呼び出し元が扱える失敗には throw を使います。break と continue は対象のループまたは switch 内だけで使用し、Stop-Process は別のローカルプロセスに限定します。データを返すかエラーを送出する関数は再利用しやすく、小さなエントリースクリプトがシェル、スケジューラ、CI、ラッパー向けの安定した終了状態へ変換できます。