次の方法で共有


about_Trap

簡単な説明

終了エラーを処理するキーワードについて説明します。

長い説明

終了エラーは、ステートメントの実行を停止します。 PowerShell で何らかの方法で終了エラーが処理されない場合、PowerShell は現在のパイプラインで関数またはスクリプトの実行も停止します。 C# などの他の言語では、終了エラーは例外と呼ばれます。

trap キーワードは、終了エラーが発生したときに実行するステートメントの一覧を指定します。 trap ステートメントは、次の方法で終了エラーを処理できます。

  • trap ステートメント ブロックを処理し、trapを含むスクリプトまたは関数の実行を継続した後、エラーを表示します。 この動作が既定です。

    手記

    if ステートメントやforeach ループなどの下位ステートメント ブロックで終了エラーが発生すると、trap ブロック内のステートメントが実行され、下位ブロックの外側の次のステートメントで実行が続行されます。

  • trap ステートメントで break を使用して、trap を含むスクリプトまたは関数のエラーと中止の実行を表示します。

  • エラーを無音にしますが、trap ステートメントで continue を使用して、trap を含むスクリプトまたは関数の実行を続行します。

trap のステートメント リストには、複数の条件または関数呼び出しを含めることができます。 trap では、ログの書き込み、テスト条件、または別のプログラムの実行を行うことができます。

構文

trap ステートメントには、次の構文があります。

trap [[<error type>]] {<statement list>}

trap ステートメントには、終了エラーが発生したときに実行するステートメントの一覧が含まれています。 trap ステートメントは、trap キーワードと、必要に応じて型式、およびエラーがトラップされたときに実行するステートメントの一覧を含むステートメント ブロックで構成されます。 型式は、trap がキャッチするエラーの種類を調整します。

スクリプトまたはコマンドには、複数の trap ステートメントを含めることができます。 trap ステートメントは、スクリプトまたはコマンド内の任意の場所に表示できます。

すべての終了エラーをトラップする

スクリプトまたはコマンドで別の方法で処理されない終了エラーが発生すると、PowerShell はエラーを処理する trap ステートメントをチェックします。 trap ステートメントが存在する場合、PowerShell は trap ステートメントでスクリプトまたはコマンドの実行を続行します。

次の例は、最小限の trap ステートメントです。

trap { 'Error found.' }

この trap ステートメントは、終了エラーをトラップします。

次の例では、ランタイム エラーの原因となるナンセンス文字列が関数に含まれています。

function TrapTest {
    trap { 'Error found.' }
    nonsenseString
}

TrapTest

この関数を実行すると、次の出力が返されます。

Error found.
nonsenseString:
Line |
   3 |      nonsenseString
     |      ~~~~~~~~~~~~~~
     | The term 'nonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.

次の例には、$_または自動変数を使用してエラーを表示するtrap ステートメント$PSItem含まれています。

function TrapTest {
    trap { "Error found: $_" }
    nonsenseString
}

TrapTest

このバージョンの関数を実行すると、次の出力が返されます。

Error found: The term 'nonsenseString' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the spelling of
the name, or if a path was included, verify that the path is correct and
try again.
nonsenseString:
Line |
   3 |      nonsenseString
     |      ~~~~~~~~~~~~~~
     | The term 'nonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.

重要

trap ステートメントは、特定の scriptblock 内の任意の場所で定義できますが、その scriptblock 内のすべてのステートメントに常に適用されます。 実行時に、ブロック内の trap ステートメントは、他のステートメントが実行される前に定義されます。 JavaScript などの他の言語では、これは ホイストと呼ばれます。 つまり、trap ステートメントは、定義されている時点を超えて実行が進んでいなくても、そのブロック内のすべてのステートメントに適用されます。 たとえば、スクリプトの最後に trap を定義し、最初のステートメントでエラーをスローする場合も、その trap がトリガーされます。

特定のエラーの捕捉

スクリプトまたはコマンドには、複数の trap ステートメントを含めることができます。 特定のエラーを処理するために、trap を定義できます。

次の例は、CommandNotFoundException trap特定のエラーをトラップする ステートメントです。

trap [System.Management.Automation.CommandNotFoundException] {
    'Command error trapped'
}

関数またはスクリプトが既知のコマンドと一致しない文字列を検出すると、この trap ステートメントは Command error trapped 文字列を表示します。 trap ステートメント の一覧を実行した後、PowerShell はエラー オブジェクトをエラー ストリームに書き込み、スクリプトを続行します。

PowerShell では、.NET 例外の種類が使用されます。 次の例では、System.Exception エラーの種類を指定します。

trap [System.Exception] { 'An error trapped' }

CommandNotFoundException エラーの種類は、System.Exception 型から継承されます。 このステートメントは、不明なコマンドによって発生したエラーをトラップします。 また、他のエラーの種類もトラップします。

エラー オブジェクトを調べることで、エラーの例外の種類を見つけることができます。 次の例は、セッションの最後のエラーの例外の完全な名前を取得する方法を示しています。

nonsenseString
$Error[0].Exception.GetType().FullName
nonsenseString: The term 'nonsenseString' is not recognized as a name of a
cmdlet, function, script file, or executable program. Check the spelling
of the name, or if a path was included, verify that the path is correct
and try again.

System.Management.Automation.CommandNotFoundException

スクリプトには複数の trap ステートメントを含めることができます。 エラーの種類ごとにトラップできる trap ステートメントは 1 つだけです。 終了エラーが発生すると、PowerShell は、実行の現在のスクリプト ブロックから、最も具体的な一致を持つ trap を検索します。

次のスクリプト例には、エラーが含まれています。 このスクリプトには、終了エラーをトラップする一般的な trap ステートメントと、trap 型を指定する特定の ステートメントが含まれています。

trap { 'Other terminating error trapped' }
trap [System.Management.Automation.CommandNotFoundException] {
  'Command error trapped'
}
nonsenseString

このスクリプトを実行すると、次の結果が生成されます。

Command error trapped
nonsenseString:
Line |
   5 |      nonsenseString
     |      ~~~~~~~~~~~~~~
     | The term 'nonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.

PowerShell は nonsenseString をコマンドレットやその他の項目として認識しないため、CommandNotFoundException エラーを返します。 特定の trap ステートメントは、この終了エラーをトラップします。

次のスクリプト例には、同じ trap ステートメントが含まれていますが、エラーは異なります。

trap { 'Other terminating error trapped' }
trap [System.Management.Automation.CommandNotFoundException] {
    'Command error trapped'
}
1/$null

このスクリプトを実行すると、次の結果が生成されます。

Other terminating error trapped
RuntimeException:
Line |
   5 |  1/$null
     |  ~~~~~~~
     | Attempted to divide by zero.

0 で除算しようとしても、CommandNotFoundException エラーは発生しません。 終了エラーをトラップするもう 1 つの trap ステートメントでは、ゼロ除算エラーがトラップされます。

スクリプト ブロックでのエラーのトラップ

既定では、終了エラーがスローされると、実行はトラップ ステートメントに移ります。 trap ブロックが実行されると、エラーの場所の後の次のステートメント ブロックに制御が戻ります。

たとえば、foreach ステートメントで終了エラーが発生すると、trap ステートメントが実行され、foreach ブロック内ではなく、foreach ブロックの後の次のステートメントで実行が続行されます。

trap { 'An error occurred!'}
foreach ($x in 3..-1) {
       "1/$x = "
       "`t$(1/$x)"
}
'after loop'
1/3 =
        0.333333333333333
1/2 =
        0.5
1/1 =
        1
1/0 =
An error occurred!
RuntimeException:
Line |
   4 |         "`t$(1/$x)"
     |              ~~~~
     | Attempted to divide by zero.
after loop

出力では、ループが最後のイテレーションまで続くことがわかります。 スクリプトが 1 を 0 で除算しようとすると、PowerShell は終了エラーをスローします。 このスクリプトは、 foreach ステートメントの残りの部分をスキップし、 try ステートメントを実行し、 foreach ステートメントの後に続きます。

エラーのトラップとスコープ

trap ステートメントと同じスクリプト ブロックで終了エラーが発生した場合、PowerShell は、trapによって定義されたステートメントの一覧を実行します。 エラーの後、ステートメントで実行が続行されます。 trap ステートメントがエラーとは異なるスクリプト ブロック内にある場合、trap ステートメントと同じスクリプト ブロック内にある次のステートメントで実行が続行されます。

たとえば、関数でエラーが発生し、trap ステートメントが関数内にある場合、スクリプトは次のステートメントで続行されます。 次のスクリプトには、エラーと trap ステートメントが含まれています。

function function1 {
    trap { 'An error: ' }
    NonsenseString
    'function1 was completed'
}

function1

このスクリプトを実行すると、次の結果が生成されます。

An error:
NonsenseString:
Line |
   3 |      NonsenseString
     |      ~~~~~~~~~~~~~~
     | The term 'NonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.
function1 was completed

関数内の trap ステートメントによってエラーがトラップされます。 メッセージを表示すると、PowerShell は関数の実行を再開します。 Function1 ステートメントが完了した後に、trap が完了したことに注意してください。

この動作を、同じエラーと trap ステートメントを持つ次の例と比較します。 この例では、trap ステートメントは関数の外部で発生します。

function function2 {
    NonsenseString
    'function2 was completed'
}

trap { 'An error:' }

function2

Function2 関数を実行すると、次の結果が生成されます。

An error:
NonsenseString:
Line |
   2 |      NonsenseString
     |      ~~~~~~~~~~~~~~
     | The term 'NonsenseString' is not recognized as a name of a cmdlet,
function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the
path is correct and try again.

この例では、function2 was completed コマンドは実行されませんでした。 どちらの例でも、終了エラーは関数内で発生します。 ただし、この例では、trap ステートメントは関数の外部にあります。 trap ステートメントの実行後、PowerShell は関数に戻りません。

注意

同じエラー条件に対して複数のトラップが定義されている場合、最初の trap (スクリプト ブロックの中で最も高い) が構文的に定義されます。

次の例では、trap が指定された whoops 1 のみが実行されます。

Remove-Item -ErrorAction Stop ThisFileDoesNotExist
trap { 'whoops 1'; continue }
trap { 'whoops 2'; continue }

重要

trap ステートメントのスコープは、コンパイルされる場所に限定されます。 関数またはドットソーススクリプト内に trap ステートメントがある場合、関数またはドットソーススクリプトが終了すると、内部のすべての trap ステートメントが削除されます。

break キーワードと continue キーワードの使用

break ステートメントの continue キーワードと trap キーワードを使用して、終了エラーの後もスクリプトまたはコマンドが引き続き実行されるかどうかを判断できます。

break ステートメントの一覧に trap ステートメントを含める場合、PowerShell は関数またはスクリプトを停止します。 次のサンプル関数では、break ステートメントで trap キーワードを使用します。

function break_example {
    trap {
        'Error trapped'
        break
    }
    1/$null
    'Function completed.'
}

break_example
Error trapped
ParentContainsErrorRecordException:
Line |
   6 |      1/$null
     |      ~~~~~~~
     | Attempted to divide by zero.

trap ステートメントには break キーワードが含まれているため、関数の実行は続行されず、Function completed 行は実行されません。

continue ステートメントに trap キーワードを含めると、エラーの原因となったステートメントの後に、breakcontinueがない場合と同様に、PowerShell が再開されます。 ただし、continue キーワードでは、PowerShell はエラー ストリームにエラーを書き込むことはありません。

次のサンプル関数では、continue ステートメントで trap キーワードを使用します。

function ContinueExample {
    trap {
        'Error trapped'
        continue
    }
    foreach ($x in 3..-1) {
       "1/$x = "
       "`t$(1/$x)"
    }
    'End of function'
}

ContinueExample
1/3 =
        0.333333333333333
1/2 =
        0.5
1/1 =
        1
1/0 =
Error trapped
End of function

エラーがトラップされた後に関数が再開され、End of function ステートメントが実行されます。 エラー ストリームにエラーは書き込まれなくなります。

注記

trap ステートメントを使用すると、scriptblock 内のすべての終了エラーが確実に処理されます。 より詳細なエラー処理を行うには、catch ステートメントを使用してトラップが定義されているtry/catch ブロックを使用します。 catch ステートメントは、関連付けられている try ステートメント内のコードにのみ適用されます。 詳細については、 about_Try_Catch_Finallyを参照してください。

こちらも参照ください