LoginSignup
25
10

More than 5 years have passed since last update.

PowerShellで例外を捕まえられない

Last updated at Posted at 2017-12-02

PowerShellでのエラー/例外処理についてにもうすこし突っ込んだことを書いたよ。(2018/11/30)

PowerShellでtry~catchをしようとしても、うまくいかない、という事がある。
Cmdletが実行されたときに発生した問題(あえて例外とは書かないよ)は、コンソールに赤字で表示される(標準エラーではなさそう…)が、Cmdletを実行してるコンテキスト(例えば実装中のスクリプトとか)では例外としては扱われない1

例外をキャッチする

そんな時、-ErrorAction Stopをつけるか、$ErrorActionPreference="Stop"としておくと、Cmdletは例外を投げてくれる。

試す。

まず、以下だと例外投げてくれないので、赤文字が出る。

取れない
PS C:\Users\bounoki> try {
    Get-LocalUser nosuchuser
} catch [Exception] {
}

Get-LocalUser : ユーザー nosuchuser が見つかりませんでした。
発生場所 行:2 文字:5
+     Get-LocalUser nosuchuser
+     ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (nosuchuser:String) [Get-LocalUser], UserNotFoundException
    + FullyQualifiedErrorId : UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand

PS C:\Users\bounoki>

以下だと例外投げてくれるので赤文字が出ない。

とれる
PS C:\Users\bounoki> try {
    Get-LocalUser nosuchuser -ErrorAction Stop
} catch [Exception] {
}

PS C:\Users\bounoki> 
とれる
PS C:\Users\bounoki> $ErrorActionPreference = "Stop"
try {
    Get-LocalUser nosuchuser
} catch [Exception] {
}

PS C:\Users\bounoki> 

例外の種類を気にしながらキャッチする

上のやり方だとExceptionで捕まえられるけど、もっと具体的な例外でキャッチするにはどうしたらよいか。
赤文字の内容見て「UserNotFoundExceptionを捕まえよう」と考えて直そうとすると、うまくいかない。

これ、PowerShellのErrorActionStopにしてスクリプトを止めようとすると、System.Management.Automation.ActionPreferenceStopExceptionがスローされるという仕様らしい。

とれる
PS C:\Users\bounoki> try {
    Get-LocalUser nosuchuser -ErrorAction Stop
} catch [System.Management.Automation.ActionPreferenceStopException] {
}

PS C:\Users\bounoki> 

例外を特定して処理したい場合は、ActionPreferenceStopExceptionを投げたきっかけの例外をif文で判断すればいいらしい、とTechNetのフォーラムで見つけた

例外を特定して処理
PS C:\Users\bounoki> try {
    Get-LocalUser nosuchuser -ErrorAction Stop
} catch [System.Management.Automation.ActionPreferenceStopException] {
    if( $_.Exception -is [Microsoft.PowerShell.Commands.UserNotFoundException]) {
        Write-Host "ユーザーがみつからないよ"
    }
}
ユーザーがみつからないよ

PS C:\Users\bounoki> 

でも、これだとExceptionでcatchしたのとあまり変わらないじゃん!

結局、catch句で条件分岐しなきゃいけないのかな。
だったら、例外吐きそうなのがCmdletくらいの場合Exceptionで取っても同じかなあ。
自分で例外をthrowするようなスクリプトを作ったときには役に立ちそう。


  1. たぶん内部的に発生した.NET側の例外などは、Cmdlet内でcatchするような実装になってるのではなかろうか。→ PowerShellでのエラー/例外処理についてにもうすこし突っ込んだことを書いたよ。(2018/11/30) 

25
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
10