短い説明
PowerShell のエラーの種類と、それらを処理するためのメカニズムについて説明します。
長い説明
PowerShell では、次の 3 つのカテゴリのエラーが区別されます。
- 終了しないエラー
- ステートメント終了エラー
- スクリプト終了エラー
各カテゴリは既定の動作が異なり、処理手法が異なる必要があるため、信頼性の高いスクリプトとモジュールを記述するには、この区別を理解することが不可欠です。
さらに、外部 (ネイティブ) プログラムは、PowerShell が独自のエラー システムとは別に追跡する終了コードによってエラーを報告します。
エラーの種類
終了しないエラー
終了しないエラーは問題を報告しますが、パイプラインは停止しません。 このコマンドは、後続の入力オブジェクトの処理を続行します。 終了しないエラーは、次の方法で生成されます。
-
Write-Errorコマンドレット - 高度な関数の
$PSCmdlet.WriteError()メソッド - 個々の入力オブジェクトで回復可能なエラーが発生するコマンドレット
既定では、PowerShell によってエラー メッセージが表示され、実行が続行されます。
# Non-terminating error: the pipeline continues after the failure
'file1.txt', 'noSuchFile.txt', 'file3.txt' | ForEach-Object {
Get-Content $_ -ErrorAction Continue
}
この例では、 Get-Content は noSuchFile.txt の終了しないエラーを報告し、 file3.txtの処理を続行します。
終了しないエラーは、既定ではcatchまたはtrapをトリガーしません。
ステートメント終了エラー
ステートメント終了エラーは、現在のステートメント (パイプライン) の実行を停止しますが、スクリプトの次のステートメントで実行が続行されます。 ステートメント終了エラーは、次の方法で生成されます。
- 高度な関数とコンパイル済みコマンドレットの
$PSCmdlet.ThrowTerminatingError()メソッド -
CommandNotFoundException(存在しないコマンドの呼び出し) やParameterBindingException(無効なパラメーター引数) などのエンジン エラー - 例外をスローする .NET メソッド呼び出し (例:
[int]::Parse('abc')
# Statement-terminating error: Get-Item fails, but the next statement runs
Get-Item -Path 'C:\NoSuchFile.txt'
Write-Output 'This still runs'
ステートメント終了エラーは、 try/catch および trapによってキャッチできます。
注
.ThrowTerminatingError() は、 -ErrorAction パラメーターを参照しません (デバッガーに入る Break 値を除く)。 ただし、 $ErrorActionPreferenceは 、エンジンのステートメント レベルハンドラーを介してステートメント終了エラーに適用されます。 たとえば、 $ErrorActionPreference = 'SilentlyContinue' は、次のステートメントでスクリプトが続行されるように、ステートメント終了エラーを抑制できます。
-ErrorAction パラメーターでこれを行うことはできません。 詳細については、「$ErrorActionPreference非対称性」 を参照してください。
スクリプト終了エラー
スクリプト終了エラーにより、呼び出し履歴全体がアンワインドされます。
try/catch ブロックまたはtrap ステートメントによってエラーがキャッチされない限り、実行は完全に停止します。 スクリプト終了エラーは、次の方法で生成されます。
-
throwキーワード - 解析エラー (スクリプトのコンパイルを妨げる構文エラー)
- 終了しないエラーは、高度でないコンテキストで
-ErrorAction Stopまたは$ErrorActionPreference = 'Stop'によってエスカレートされます。 詳細については、「 エスカレーションのしくみ」を参照してください。 - 特定の重大なエンジンエラー
# Script-terminating error: throw unwinds the call stack
function Test-Throw {
throw 'Critical failure'
Write-Output 'This never runs'
}
Test-Throw
Write-Output 'This never runs either (unless caught)'
throw キーワードは、既定でスクリプト終了エラーを生成します。 ただし、$ErrorActionPreferenceSilentlyContinueまたはIgnoreに設定すると、throwを抑制できます。
-ErrorAction SilentlyContinueを使用して高度な関数を呼び出すと、パラメーターはスコープローカルの$ErrorActionPreference値に変換されるため、その関数内のthrowも抑制されます。
注
$ErrorActionPreference = 'Ignore'の場合でも、抑制されたthrowでは、$Errorにエントリが記録されます。
Ignore値は、終了しないエラーの$Error記録のみを防止します。
Important
ステートメント終了とスクリプト終了という用語は、エラーの重大度ではなく、影響の範囲を表します。 ステートメント終了エラーは、1 つのステートメントを停止します。 スクリプト終了エラーは、スクリプト全体とその呼び出し元を停止します。 どちらも try/catchでキャッチできます。
外部プログラム エラー
外部 (ネイティブ) プログラムは、PowerShell のエラー システムに直接参加しません。 0 以外の終了コードを使用してエラーを報告します。このコードは、PowerShell によって $LASTEXITCODE 自動変数に格納されます。
git clone https://example.com/nonexistent.git 2>$null
if ($LASTEXITCODE -ne 0) {
Write-Error "git failed with exit code $LASTEXITCODE"
}
既定では、ネイティブ プログラムからの 0 以外の終了コード:
-
$?を に設定します$false - で
ErrorRecordを生成しません$Error -
catchまたはtrap
PowerShell 7.3 では、試験的なユーザー設定変数 $PSNativeCommandUseErrorActionPreferenceが追加され、7.4 で安定した機能になりました。 この変数を $true に設定すると、0 以外の終了コードによって、メッセージに特定の終了コード (NativeCommandExitException) を示す終了しないエラーが出力されます。 このエラーは $ErrorActionPreferenceを考慮するため、 Stop に設定すると、 try/catchでキャッチできるスクリプト終了エラーにエラーが昇格されます。
エラー状態変数
PowerShell では、現在のエラー状態を反映する複数の自動変数が保持されます。
$?
最後の操作が成功した場合に $true を格納し、エラー (非終了または終了) が発生した場合に $false します。 ネイティブ コマンドの場合、$?は終了コードに基づいて設定されます。終了コード0の$true、それ以外の場合は$false。
Get-Item -Path 'C:\NoSuchFile.txt' 2>$null
$? # False
$Error
インデックス 0で最新のエラーが発生した最新のエラー レコードを格納するArrayList。 リストには最大 $MaximumErrorCount エントリが保持されます (既定値は 256)。
終了するすべてのエラーが $Errorに追加されます。 終了エラーの場合、 Ignore 表示は抑制されますが、エラーは $Errorに記録されます。 終了しないエラーで-ErrorAction Ignoreが使用されていない限り、すべての非終了が$Errorに追加されます。これにより、表示と記録の両方が妨げられます。
$LASTEXITCODE
最後に実行されたネイティブ プログラムの終了コードが含まれます。
0の値は、従来は成功を示します。 0 以外の値は失敗を示します。 この変数は、PowerShell コマンドレット エラーの影響を受けません。
エラーの動作を制御する
-ErrorAction共通パラメーター
-ErrorAction共通パラメーターは、1 つのコマンドの$ErrorActionPreferenceをオーバーライドします。 PowerShell がそのコマンドから 終了しない エラーに応答する方法を制御します。
| 価値 | 行動 |
|---|---|
Continue |
エラーを表示して続行する (既定) |
SilentlyContinue |
表示を抑制し、 $Errorに追加し、続行する |
Ignore |
表示を抑制し、追加しない $Error |
Stop |
終了エラーにエスカレートする (エスカレーションのしくみを参照) |
Inquire |
ユーザーに決定を求める |
Break |
デバッガーを入力する |
-ErrorAction では、 $PSCmdlet.ThrowTerminatingError()によって生成されるエラーの動作は変更されません。 これらのエラーは、呼び出し元の設定に関係なく、常にステートメントで終了します。
$ErrorActionPreference 可変
$ErrorActionPreference基本設定変数は、現在のスコープと子スコープ内のすべてのコマンドに適用されます。
-ErrorActionと同じ値を受け取ります。
$ErrorActionPreference = 'Stop'
# All non-terminating errors in this scope now become terminating
Write-Error 'This now throws' # Generates ActionPreferenceStopException
コマンドで -ErrorAction を指定すると、そのコマンドの $ErrorActionPreference よりも優先されます。
エスカレーションのしくみ
-ErrorAction Stopまたは$ErrorActionPreference = 'Stop'が有効な場合、PowerShell は、次のメカニズムを使用して、終了しないエラーを終了エラーに変換します。
- コマンドレットは
WriteError()を内部的に呼び出して、終了しないエラーを出力します。 - エンジンは、コマンドの有効な
ErrorAction設定を確認します。 - 基本設定は
Stopであるため、エンジンは元のエラー レコードをラップするActionPreferenceStopExceptionを作成します。 -
catchによってキャッチされた場合、元のエラー情報には$_.Exception.ErrorRecordを介してアクセスできます。
エスカレートされたエラーのスコープは、コンテキストによって異なります。
-
高度でないスクリプト、関数、またはスクリプト ブロックでは、
$ErrorActionPreference = 'Stop'設定がスクリプト終了エラーにエスカレートされます。 エラーによって呼び出し履歴が伝達されます。 -
高度な関数とスクリプト ブロック (
[CmdletBinding()]を含む) では、エラーはステートメント終了のままです。 実行は、呼び出しの後の次のステートメントで続行されます。 -
-ErrorAction Stopを高度な関数に渡すことは、その中で$ErrorActionPreference = 'Stop'を設定する場合と同じ効果があります。これは、-ErrorActionがスコープ ローカルの$ErrorActionPreference値に変換されるためです。
エスカレーションの例
NON-advanced: script-terminating ('after' does not print)
& { param() $ErrorActionPreference = 'Stop' Get-Item 'NoSuchPath' } 2>$null 'after'ADVANCED: ステートメント終了 ('after' DOES print)
& { [CmdletBinding()] param() $ErrorActionPreference = 'Stop'; Get-Item 'NoSuchPath' } 2>$null 'after'-ErrorAction Stopなし: 非終了、catch は実行されませんtry { Write-Error 'This is non-terminating' Write-Output 'Execution continues' } catch { Write-Output "Caught: $_" # Not reached }-ErrorAction Stop: 終了にエスカレートtry { Write-Error 'This becomes terminating' -ErrorAction Stop } catch { Write-Output "Caught: $_" # Reached }
エスカレートされたエラーは、元の例外の種類によってキャッチできます。 エンジンは、基になる例外を見つけるために ActionPreferenceStopException をラップ解除します。
try {
Get-Item -Path 'C:\NoSuchFile.txt' -ErrorAction Stop
} catch [System.Management.Automation.ItemNotFoundException] {
Write-Output "File not found: $($_.Exception.Message)"
}
$ErrorActionPreference非対称
-ErrorAction パラメーターと$ErrorActionPreference変数は、終了エラーと共に動作が異なります。 この非対称性を理解することが重要です。
-ErrorActionは、 終了しない エラーにのみ影響します。 コマンドレットが$PSCmdlet.ThrowTerminatingError()を呼び出すと、-ErrorActionパラメーターは無視されます (デバッガーに入るBreakを除く)。 エラーは常にスローされます。$ErrorActionPreferenceは、非終了エラーとステートメント終了エラーの 両方 に影響します。 エンジンのステートメント レベルのエラー ハンドラーは 、(-ErrorActionパラメーターではなく)$ErrorActionPreferenceを読み取り、値がSilentlyContinueまたはIgnoreされたときにステートメント終了エラーを抑制できます。
function Test-Asymmetry {
[CmdletBinding()]
param()
$er = [System.Management.Automation.ErrorRecord]::new(
[System.InvalidOperationException]::new('test error'),
'TestError',
[System.Management.Automation.ErrorCategory]::InvalidOperation,
$null
)
$PSCmdlet.ThrowTerminatingError($er)
}
# -ErrorAction SilentlyContinue does NOT suppress the error:
Test-Asymmetry -ErrorAction SilentlyContinue # Error is still thrown
# $ErrorActionPreference DOES suppress the error:
$ErrorActionPreference = 'SilentlyContinue'
Test-Asymmetry # Error is silently suppressed, script continues
$ErrorActionPreference = 'Continue'
Important
$ErrorActionPreference では、 SuppressPromptInInterpreter が true に設定されているエラーを抑制できません。 これらは、ユーザー設定変数に関係なく常に伝達されます。 この種類のエラーの例を次に示します。
-
ActionPreferenceStopExceptionエスカレーションからの-ErrorAction Stop - PowerShell クラス メソッド内のエラー
PipelineStoppedException
エラーの処理
try/catch/finally
try/catch/finallyを使用して、ステートメント終了エラーとスクリプト終了エラーを処理します。
try ブロック内でエラーが発生すると、PowerShell は一致するcatch ブロックを検索します。 エラーが発生したかどうかにかかわらず、 finally ブロックは常に実行されます。
try {
$result = Get-Content -Path 'data.txt' -ErrorAction Stop
}
catch [System.Management.Automation.ItemNotFoundException] {
Write-Warning 'Data file not found, using defaults.'
$result = 'default'
}
catch {
Write-Warning "Unexpected error: $_"
}
finally {
Write-Verbose 'Cleanup complete.' -Verbose
}
try ブロック内では、エンジンによって内部フラグが設定され、-ErrorAction Stopまたは$ErrorActionPreference = 'Stop'によって終了しないエラーがcatch ブロックに伝達されます。 これは特別なケースではなく、設計された動作です。
構文の詳細については、 about_Try_Catch_Finallyを参照してください。
trap
trap ステートメントは、スコープ レベルで終了エラーを処理します。 外側のスコープ内の任意の場所でエラーが発生すると、 trap ブロックが実行されます。
-
既定値 (
breakまたはcontinueなし): エラーが表示され、エラーの原因となったステートメントの後の次のステートメントで実行が続行されます。 -
continuein the trap: エラー メッセージを抑制し、次のステートメントで再開します。 -
breakトラップ内: エラーは親スコープに伝達されます。
trap [System.Management.Automation.CommandNotFoundException] {
Write-Warning "Command not found: $($_.TargetObject)"
continue
}
NonsenseCommand # Trap fires, execution continues
Write-Output 'This runs because the trap used continue'
構文の詳細については、 about_Trapを参照してください。
関数とスクリプトのエラーの報告
関数とスクリプトを記述するときは、エラーの重大度に一致するエラー報告メカニズムを選択します。
非終了 - 使用 Write-Error
関数が他の入力の処理を続行できる場合は、 Write-Error を使用します。 これは、複数のオブジェクトを処理し、個々の項目でエラーが発生するパイプライン関数に適しています。
function Test-Path-Safe {
[CmdletBinding()]
param([Parameter(ValueFromPipeline)][string]$Path)
process {
if (-not (Test-Path $Path)) {
Write-Error "Path not found: $Path"
return
}
$Path
}
}
注
高度な関数 ([CmdletBinding()]を使用する関数) では、Write-Errorではなく$PSCmdlet.WriteError()を使用して、$?が呼び出し元のスコープで$falseに適切に設定されていることを確認します。
Write-Error コマンドレットは、常に$?正しく設定されているわけではありません。
ステートメントの終了 - use $PSCmdlet.ThrowTerminatingError()
関数をまったく続行できないが、呼び出し元がエラーの処理方法を決定する必要がある場合は、 $PSCmdlet.ThrowTerminatingError() を使用します。 これは、高度な関数で推奨されるアプローチです。
function Get-Config {
[CmdletBinding()]
param([string]$Path)
if (-not (Test-Path $Path)) {
$er = [System.Management.Automation.ErrorRecord]::new(
[System.IO.FileNotFoundException]::new("Config file not found: $Path"),
'ConfigNotFound',
[System.Management.Automation.ErrorCategory]::ObjectNotFound,
$Path
)
$PSCmdlet.ThrowTerminatingError($er)
}
Get-Content $Path | ConvertFrom-Json
}
エラーが関数から離れると、呼び出し元は既定で終了しないエラーとして扱います。 呼び出し元は、 -ErrorAction Stopを使用してエスカレートできます。
スクリプトの終了 - 使用 throw
復旧できず、スクリプト全体が停止する必要がある場合は、 throw を使用します。
$config = Get-Content 'config.json' -ErrorAction SilentlyContinue |
ConvertFrom-Json
if (-not $config) {
throw 'Cannot proceed without a valid configuration file.'
}
使用するメカニズム
- 一部の入力が失敗する可能性がある複数の入力を処理する場合は、
Write-Errorまたは$PSCmdlet.WriteError()を使用します。 - 関数を続行できない場合は、
$PSCmdlet.ThrowTerminatingError()を使用し、呼び出し元が処理方法を決定できるようにします。 - スクリプト全体を直ちに停止する必要がある場合は、
throwを使用します。
エラーの種類の概要
次の表は、PowerShell のさまざまなエラーの種類のプロパティと動作をまとめたものです。
終了しないエラー
終了しないエラー は、 Write-Error または $PSCmdlet.WriteError()によって生成できます。
| 特性 | 説明 |
|---|---|
| 影響の及ぶ範囲 | パイプラインの続行 |
キャッチ者 catch |
いいえ (エスカレートされていない場合) |
キャッチ者 trap |
いいえ (エスカレートされていない場合) |
に追加 $Error |
はい ( Ignoreを除く) |
$? を に設定します$false |
はい |
影響を受ける -ErrorAction |
はい |
影響を受ける $ErrorActionPreference |
はい |
ステートメント終了エラー
ステートメント終了エラー は、 ThrowTerminatingError()、エンジン エラー、.NET メソッドの例外、または高度なコンテキストでの -ErrorAction Stop によって生成できます。
| 特性 | 説明 |
|---|---|
| 影響の及ぶ範囲 | 現在のステートメントは停止します。スクリプトを続行する |
キャッチ者 catch |
はい |
キャッチ者 trap |
はい |
に追加 $Error |
はい |
$? を に設定します$false |
はい |
影響を受ける -ErrorAction |
いいえ (Break のみ) |
影響を受ける $ErrorActionPreference |
はい (抑制できます) |
スクリプト終了エラー
スクリプト終了エラー は、高度でないコンテキストで throw、解析エラー、または -ErrorAction Stop によって生成できます。
| 特性 | 説明 |
|---|---|
| 影響の及ぶ範囲 | 呼び出し履歴のアンワインド |
キャッチ者 catch |
はい |
キャッチ者 trap |
はい |
に追加 $Error |
はい |
$? を に設定します$false |
はい |
影響を受ける -ErrorAction |
いいえ |
影響を受ける $ErrorActionPreference |
throw: はい (抑制できます) |
影響を受ける $ErrorActionPreference |
エスカレート: コンテキストに依存 |
こちらも参照ください
PowerShell