2010年09月10日

[PowerShell] 例外を補足する

 PowerShell には例外補足機能がついていて、trap { } と記述します。trapは、C#に出てくるようなtry 〜 catch 文とは異なっていて、なかなか特徴的な動作をします。
人気ブログランキング

trapを書く位置


 スクリプトブロックのどかこにtrapを書くと、trapを書いた位置より後ろ(↓)で発生した例外はもちろん補足しますが、前で発生した例外も補足します。

■TrapTest1.ps1
1/$null

trap
{
  Write-Host "例外を補足しました。"
  exit
}

■実行結果
PS U:\> .\Scripts\TrapTest.ps1
例外を補足しました。
PS U:\>

 例外は1/$nullのところで発生しますが、その下に書いたtrapで例外を補足しました。

スクリプトブロック内で発生した例外


 trap内でcontinueと記述すると、trapブロックに書かれた処理を実行したのち、例外が発生した次の行からスクリプトが再開されます。

 ただし、スクリプトブロック内で例外が発生しした場合は、trapが発生したスクリプトブロックのレベルで考えた次の命令を実行します。次の場合、trapはifの外に書かれているため、ifのスクリプトブロックが1つの文とみなされ、ifの次の文からスクリプトを実行します。

■TrapTest2.ps1
Write-Host "  実行A"
if($true)
{
  Write-Host "  実行B"
  1/$null
  Write-Host "  実行C"
}
Write-Host "  実行D"

trap
{
  Write-Host "  例外を補足しました。"
  continue
}

■実行結果
PS U:\> .\Scripts\TrapTest2.ps1
  実行A
  実行B
  例外を補足しました。
  実行D
PS U:\>

 ifは{ }全体で1つの文と考えられるため、「実行C」とは表示されませんでした。

一度補足した例外を再度補足する


 trapで補足した際、breakと記述すると、breakのところで再び例外が発生したかのような動作をします。さらに、break文で発生した(ように見える)例外を、他のtrapで補足することができます。

■TrapTest3.ps1
Write-Host "  実行A"
if($true)
{
  Write-Host "  実行B"
  1/$null
  Write-Host "  実行C"
  trap
  {
    Write-Host "  例外[1]を補足しました。"
    break
  }
}
Write-Host "  実行D"

trap
{
  Write-Host "  例外[2]を補足しました。"
  continue
}

■実行結果
PS U:\> .\Scripts\TrapTest3.ps1
  実行A
  実行B
  例外[1]を補足しました。
  例外[2]を補足しました。
  実行D
PS U:\>

 if内のtrapでbreakが実行されたので、その外側のスクリプトブロックに書かれているtrapで例外を補足しました。

trapの中で変更された値


 trapのスクリプトブロック内で変数を使用した場合、その変数は、スクリプトブロックの外の変数をコピーした別の変数であるかのように振る舞います。

 したがって、trapのスクリプトブロック内で値を変更した場合、スクリプトブロックの外の変数には影響が及びません。

 ただし、参照型変数の参照先であるオブジェクトを変更した場合は、スクリプトブロックの外にも影響が及びます。

■TrapTest4.ps1
$obj=New-Object PSObject
$obj | Add-Member NoteProperty Value 0

$x=1; $obj.Value=1
Write-Host ("  [A1] x={0}, o.V={1}" -f $x,$obj.Value)
1/$null
Write-Host ("  [A2] x={0}, o.V={1}" -f $x,$obj.Value)

trap
{
  Write-Host ("  [B1] x={0}, o.V={1}" -f $x,$obj.Value)
  $x=2; $obj.Value=2
  Write-Host ("  [B2] x={0}, o.V={1}" -f $x,$obj.Value)
  continue
}

■実行結果
PS U:\> .\Scripts\TrapTest.ps1
  [A1] x=1, o.V=1
  [B1] x=1, o.V=1
  [B2] x=2, o.V=2
  [A2] x=1, o.V=2
PS U:\>

 trap{ }内の$xは値型変数なので、trap内で$xを変更してもtrapの外$xの値は変わりませんでした。$objは参照型変数なのでtrap内の変更がtrapの外にも影響しました。

 この違いをファイル操作にたとえると、ファイル本体をコピーした場合とショートカットをコピーした場合の違いのようなものです。

 値型変数(この場合は$x)はファイル本体がコピーされるようなものなので、コピー先を変更してもコピー元には影響しません。

 参照型変数(同じく$obj)はショートカットをコピーするようなもので、コピー先ショートカットからファイルを開いて内容を変更すると、コピー元のショートカットからファイルを開いても更新された内容が見えます。
web拍手 by FC2
タグ:TRAP
posted by 北条利彦 at 22:54 | Comment(0) | TrackBack(0) | PowerShell | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
この記事へのトラックバックURL
http://blog.seesaa.jp/tb/162179791

この記事へのトラックバック
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。