次の方法で共有


about_Error_Handling

短い説明

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-ContentnoSuchFile.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 は、次のメカニズムを使用して、終了しないエラーを終了エラーに変換します。

  1. コマンドレットは WriteError() を内部的に呼び出して、終了しないエラーを出力します。
  2. エンジンは、コマンドの有効な ErrorAction 設定を確認します。
  3. 基本設定は Stopであるため、エンジンは元のエラー レコードをラップする ActionPreferenceStopException を作成します。
  4. 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 では、 SuppressPromptInInterpretertrue に設定されているエラーを抑制できません。 これらは、ユーザー設定変数に関係なく常に伝達されます。 この種類のエラーの例を次に示します。

  • 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なし): エラーが表示され、エラーの原因となったステートメントの後の次のステートメントで実行が続行されます。
  • continue in 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 エスカレート: コンテキストに依存

こちらも参照ください