次の方法で共有


about_Trap

簡単な説明

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

詳細な説明

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

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

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

    Note

    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 : 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.
At line:3 char:5
+     nonsenseString
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (nonsenseString:String) []
   , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

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

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 : 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.
At line:3 char:5
+     nonsenseString
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (nonsenseString:String) []
   , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

重要

trap ステートメントは、特定のスクリプト ブロック内の任意の場所で定義できますが、そのスクリプト ブロック内のすべてのステートメントに常に適用されます。 実行時に、ブロック内の trap ステートメントは、他のステートメントが実行される前に定義されます。 JavaScript では、これは hoisting と呼ばれます。 つまり、 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 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.
At line:1 char:1
+ nonsenseString
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (nonsenseString:String) []
   , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

System.Management.Automation.CommandNotFoundException

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

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

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

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

Command error trapped
nonsenseString : 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.
At line:5 char:1
+ nonsenseString}
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (nonsenseString:String) []
   , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

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

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

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

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

Other terminating error trapped
Attempted to divide by zero.
At line:5 char:1
+ 1/$null}
+ ~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

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!
Attempted to divide by zero.
At line:3 char:4
+    1/$x
+    ~~~~
    + CategoryInfo          : NotSpecified: (:) [], RuntimeException
    + FullyQualifiedErrorId : RuntimeException

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 : 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.
At line:3 char:5
+     NonsenseString
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (NonsenseString:String) []
   , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

function1 was completed

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

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

function function2 {
    NonsenseString
    'function2 was completed'
}

trap { 'An error:' }

function2

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

An error:
NonsenseString : 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.
At line:2 char:5
+     NonsenseString
+     ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (NonsenseString:String) []
   , CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

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

注意事項

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

次の例では、whoops 1を含むtrapのみが実行されます。

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

重要

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

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

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

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

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

break_example
Error trapped
Attempted to divide by zero.
At line:6 char:5
+     1/$null
+     ~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], ParentContainsErrorR
   ecordException
    + FullyQualifiedErrorId : RuntimeException

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

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

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

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

関連項目