PowerShell例外処理

PowerShellのtry-catchについて

try-catchの基本書式

PowerShell v2.0から try,catch,finallyステートメントがサポートされるようになりました。

基本書式は以下の通りです。


try{
    # 例外をスローする可能性のある処理
}catch [例外]{
    # 例外処理(例外ハンドラ)
}finally{
    # 最後に必ず実行される処理 
}

例外を複数指定する場合は、カンマで区切ります。


} catch [例外1], [例外2] {

throwについて

意図的な例外の発生は throw で行います。

下記例では処理3を行うことなくにcatchされ、finallyに進みます。

なお、例外をException(実質的には全てのエラーを拾う)にしています。


$rc=0

Write-Host "処理開始"
try{
    Write-Host "処理1を実行します。"
    Write-Host "処理2を実行します。"
    throw "Exception : 例外発生"
    Write-Host "処理3を実行します。"
}catch [Exception]{
    Write-Host "catch例外処理です"
    Write-host $error
    $rc = 1
}finally{
    Write-Host "finally処理です。"
}
Write-Host "処理終了"
exit $rc

$error変数について

例外の詳細は $Error自動変数に自動的に格納されます。

$Error変数内部には、過去に発生した例外のリストが格納されており、直前に発生した例外は$Error[0]に入っています。


コマンドレットを例外としてcatchできない場合について

PowerShellのエラーには「終了するエラー」と「続行するエラー」があり、デフォルトでCatchできるのは「終了するエラー」だけです。

そのため、単純にコマンドレットで利用しようとしてもCatch節で例外を捉えられません。(trap{}ステートメントでも同様です。)


例外をcatchする挙動は、 $ErrorActionPreference自動変数で定義されています。

デフォルトでは「Continue」が設定されているため、「続行するエラー」についてcatchせずに処理を続行してしまう動作となります。


例えば、$ErrorActionPreference自動変数の値を「Stop」にすることで、コマンドレットのエラーを例外として捕捉することが可能となります。


$ErrorActionPreference = "Stop"
$rc = 0

try{
    Write-Host "処理1を実行します。"
    # ファイルへ書き込み
    Set-Content -Path ".\not_exist\not_exist.txt" -Value "test"
    Write-Host "処理2を実行します。"
}catch{
    Write-Host "catch例外処理です"
    Write-host $error
    $rc = 1
}finally{
    Write-Host "finally処理です。"
}

exit $rc

$ErrorActionPreference自動変数に設定できる値と意味は以下の通りです。

なお、以下のいずれを選択してもエラー出力は$errorに追加され、$?はfalseになります。

continue 例外は出力しつつ、処理も継続する。デフォルト動作です。
silentlycontinue 例外を出力せずに、処理を継続する
stop 処理を終了する。

PowerShellのtrapについて

trapの基本書式

trapの基本書式は以下の通りです。


trap [例外]{
    # 例外処理(例外ハンドラ)
}

trap内の break, continue

例外が発生すると、デフォルトではtrap処理と例外メッセージを表示した後、スクリプトを継続して後続処理に移ります。

例外発生時点で処理を止めたい場合にはtrap内に「break」を記述します。

また、例外発生を無視して処理を継続したい場合には「continue」を指定します。


function ps_exception_1($num)
{
  trap [Exception] {
    write-host("ps_exception_1():trap")
    continue
  }

  Write-Host "ps_exception_1():処理1を実行します。"
  5/$num
  Write-Host "ps_exception_1():処理2を実行します。"
}

function ps_exception_2($num)
{

  trap [Exception] {
    write-host("ps_exception_2():trap")
    break
  }

  Write-Host "ps_exception_2():処理1を実行します。"
  5/$num
  Write-Host "ps_exception_2():処理2を実行します。"
}

Write-Host "処理を開始します。"
ps_exception_1 0
ps_exception_2 0
Write-Host "処理を終了します。"

実行結果は以下の通りです。


>powershell .\trap.ps1
処理を開始します。
ps_exception_1():処理1を実行します。
ps_exception_1():trap
ps_exception_1():処理2を実行します。
ps_exception_2():処理1を実行します。
ps_exception_2():trap
0 で除算しようとしました。
発生場所 C:\trap.ps1:24 文字:5
+   5/ <<<< $num
    + CategoryInfo          : NotSpecified: (:) []、ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RuntimeException

関連ページ