Help us understand the problem. What is going on with this article?

Powershellスクリプト 例外処理の罠

More than 3 years have passed since last update.

はじめに

Powershellで大き目の規模の自動化スクリプトを開発する際のエラーハンドルではまりやすいところ

例外ハンドルについて

Powershellスクリプトで例外をcatchする場合は以下のとおり記述します。

test.ps1
try{
    #write some code
}catch{
    #write some code if error occured
}finally{
    #write some code
}

しかし、Powershellでは.NetのPowershellのコマンドレットだけでなく、net useのようなコマンドを利用することがあります。

この場合、以下のように記述してもエラーをハンドルできません。

test.ps1
try{
    net use \\hostname\share password /user:user
}catch{
    Write-Error("エラー"+$_.Exception)
}finally{
    #write some code
}

これは、netuse.exeを実行した結果を文字列で出力されるだけで、エラーを扱うには一工夫必要です。
また、ファイル操作系のコマンド実行でもエラーがcatchされないことがありました。

test.ps1
try{
    Move-Item -Path "SrcPath" -Destination "DstPath"
}catch{
    Write-Error("エラー"+$_.Exception)
}finally{
    #write some code
}

① エラー判定

環境変数「$LASTEXITCODE」を利用する

例としてnet useコマンドを例に挙げましたが、.exeファイルの実行後、Powershellの環境変数である$LASTEXITCODEに値が格納されます。

一般的には、正常終了していれば0が格納されており、以下のようにできます。

test.ps1
try{
    net use \\hostname\share password /user:user
    if($LASTEXITCODE -ne 0){
        throw
    }
}catch{
    Write-Error("エラー"+$_.Exception)
}finally{
    #write some code
}

ただ、これが使えるのは外部スクリプトの実行の場合なので、上記ファイル操作系のコマンドには利用できません。
なので、ファイル操作系は以下のオプションを利用します。

test.ps1
try{
    Move-Item -Path "SrcPath" -Destination "DstPath" -ErrorAction Stop
}catch{
    Write-Error("エラー"+$_.Exception)
}finally{
    #write some code
}

② エラー内容

エラーの内容を取得するには以下の方法があります。

1. $.Exception($.Exception.Message)

発生した直近の例外が格納されています。
catch句の中で利用します。

2. $ERROR

セッション内で発生したエラーを配列で格納しています。
net useコマンドでエラーが発生した場合もエラー内容を保持しています。

Powershell勉強中のため、マサカリどんどんお待ちしてます。

NakaD
@_KaguyaLuna
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away