Windows PowerShell 5.1 で確認。
構文エラー
パース段階でエラーが起きた場合、スクリプト全体が実行されない。例えば次のスクリプトを実行しようとしたとき、「###Start###」も「###End###」も表示されない。後述の trap
ブロックや catch
ブロックがあっても実行されない。
Write-Output "###Start###"
$syntaxError = (1/)
Write-Output "###End###"
PS C:\> .\error_test.ps1
発生場所 C:\error_test.ps1:2 文字:19
+ $syntaxError = (1/)
+ ~
'/' 演算子に続けて値の式を指定する必要があります。
+ CategoryInfo : ParserError: (:) [], ParseException
+ FullyQualifiedErrorId : ExpectedValueExpression
実行時エラー
ErrorAction
デフォルトでは、実行時エラーが起きてもスクリプトの実行が継続する。これは、ErrorAction
パラメーターのデフォルト値が Continue
であるため。
Write-Output "###Start###"
$divideByZero = (1/0)
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
0 で除算しようとしました。
発生場所 C:\error_test.ps1:2 文字:1
+ $divideByZero = (1/0)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
### End###
ErrorAction
パラメーターの値を Stop
にすると、エラーが起きた時点でスクリプトが停止する。
$ErrorActionPreference = "Stop"
Write-Output "###Start###"
$divideByZero = (1/0)
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
0 で除算しようとしました。
発生場所 C:\error_test.ps1:3 文字:1
+ $divideByZero = (1/0)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : RuntimeException
「###End###」が表示されなくなった。例外のクラスが RuntimeException
から ParentContainsErrorRecordException
に変わっているが、なぜかは私にはわからない。
個々のコマンドレットで発生する実行時エラーに対しては、コマンドレットごとに ErrorAction
の値を設定することもできる。
Write-Output "###Start###"
Get-ChildItem "NotExist" -ErrorAction "Stop"
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:2 文字:1
+ Get-ChildItem "NotExist" -ErrorAction "Stop"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
Trap
スクリプトの任意の位置に trap
ブロックを置くと、エラーが起きたときに、trap
ブロックの中身が実行されたのちエラーメッセージが出力される。trap
ブロックの中では、エラーの内容を $_
で参照できる。
Write-Output "###Start###"
$divideByZero = (1/0)
Write-Output "###End###"
trap {
Write-Output "###Trap start###"
Write-Output $_
Write-Output "###Trap end###"
}
PS C:\> .\error_test.ps1
### Start###
### Trap start###
0 で除算しようとしました。
発生場所 C:\error_test.ps1:2 文字:1
+ $divideByZero = (1/0)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], DivideByZeroException
+ FullyQualifiedErrorId : RuntimeException
### Trap end###
0 で除算しようとしました。
発生場所 C:\error_test.ps1:2 文字:1
+ $divideByZero = (1/0)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
### End###
ErrorAction
の値が Continue
なので「###End###」が表示されている。trap
で捕捉された例外とエラーメッセージに表示される例外が異なるが、なぜかは私にはわからない。
デフォルトでは、つまり ErrorAction
の値が Continue
の場合、個々のコマンドレットで発生する実行時エラーは捕捉されない。
Write-Output "###Start###"
Get-ChildItem "NotExist"
Write-Output "###End###"
trap {
Write-Output "###Trap start###"
Write-Output $_
Write-Output "###Trap end###"
}
PS C:\> .\error_test.ps1
### Start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:2 文字:1
+ Get-ChildItem "NotExist"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### End###
個々のコマンドレットでの実行時エラーを捕捉するには、そのコマンドレットで ErrorAction
の値を Stop
にする。この場合も、スクリプトの実行はエラーが起きた後も継続する。
Write-Output "###Start###"
Get-ChildItem "NotExist" -ErrorAction "Stop"
Write-Output "###End###"
trap {
Write-Output "###Trap start###"
Write-Output $_
Write-Output "###Trap end###"
}
PS C:\> .\error_test.ps1
### Start###
### Trap start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:2 文字:1
+ Get-ChildItem "NotExist" -ErrorAction "Stop"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Trap end###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:2 文字:1
+ Get-ChildItem "NotExist" -ErrorAction "Stop"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### End###
スクリプト全体で ErrorAction
の値を Stop
にすると、エラーを捕捉できるだけでなく、エラーが起きたときにスクリプトの実行が止まる。
$ErrorActionPreference = "Stop"
Write-Output "###Start###"
Get-ChildItem "NotExist"
Write-Output "###End###"
trap {
Write-Output "###Trap start###"
Write-Output $_
Write-Output "###Trap end###"
}
PS C:\> .\error_test.ps1
### Start###
### Trap start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:3 文字:1
+ Get-ChildItem "NotExist"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Trap end###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:3 文字:1
+ Get-ChildItem "NotExist"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
Try Catch Finally
try
ブロックの中で実行時エラーが起きると、処理が catch
ブロックに移る。trap
と同様、catch
ブロックの中でもエラーの内容を $_
で参照できる。ただし、trap
と異なり、エラーメッセージは出力されない。
Write-Output "###Start###"
try {
Write-Output "###Try start###"
$divideByZero = (1/0)
Write-Output "###Try end###"
} catch {
Write-Output "###Catch start###"
Write-Output $_
Write-Output "###Catch end###"
}
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
### Try start###
### Catch start###
0 で除算しようとしました。
発生場所 C:\error_test.ps1:4 文字:3
+ $divideByZero = (1/0)
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
### Catch end###
### End###
trap
と同様、個々のコマンドレットで起きる実行エラーは捕捉されず、エラーメッセージが出力される。
Write-Output "###Start###"
try {
Write-Output "###Try start###"
Get-ChildItem "NotExist"
Write-Output "###Try end###"
} catch {
Write-Output "###Catch start###"
Write-Output $_
Write-Output "###Catch end###"
}
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
### Try start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:4 文字:3
+ Get-ChildItem "NotExist"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Try end###
### End###
ErrorAction
の値を Stop
にすると、エラーを捕捉できるようになる。
Write-Output "###Start###"
try {
Write-Output "###Try start###"
Get-ChildItem "NotExist" -ErrorAction "Stop"
Write-Output "###Try end###"
} catch {
Write-Output "###Catch start###"
Write-Output $_
Write-Output "###Catch end###"
}
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
### Try start###
### Catch start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:4 文字:3
+ Get-ChildItem "NotExist" -ErrorAction "Stop"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Catch end###
### End###
スクリプト全体で ErrorAction
の値を Stop
にしていても、try
ブロックの中でエラーが起きた場合、catch
ブロックの後にあるスクリプトが実行される。
$ErrorActionPreference = "Stop"
Write-Output "###Start###"
try {
Write-Output "###Try start###"
Get-ChildItem "NotExist"
Write-Output "###Try end###"
} catch {
Write-Output "###Catch start###"
Write-Output $_
Write-Output "###Catch end###"
}
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
### Try start###
### Catch start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:5 文字:3
+ Get-ChildItem "NotExist" -ErrorAction "Stop"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Catch end###
### End###
エラーが起きた後にスクリプトの実行を止めたい場合、catch
ブロックの末尾に break
を置く。
$ErrorActionPreference = "Stop"
Write-Output "###Start###"
try {
Write-Output "###Try start###"
Get-ChildItem "NotExist"
Write-Output "###Try end###"
} catch {
Write-Output "###Catch start###"
Write-Output $_
Write-Output "###Catch end###"
break
}
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
### Try start###
### Catch start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:5 文字:3
+ Get-ChildItem "NotExist"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Catch end###
エラーが起きても起きなくても実行するスクリプトがある場合は、finally
ブロックに記述する。
$ErrorActionPreference = "Stop"
Write-Output "###Start###"
try {
Write-Output "###Try start###"
Get-ChildItem "NotExist"
Write-Output "###Try end###"
} catch {
Write-Output "###Catch start###"
Write-Output $_
Write-Output "###Catch end###"
break
} finally {
Write-Output "###Finally###"
}
Write-Output "###End###"
PS C:\> .\error_test.ps1
### Start###
### Try start###
### Catch start###
Get-ChildItem : パス 'C:\NotExist' が存在しないため検出できません。
発生場所 C:\error_test.ps1:5 文字:3
+ Get-ChildItem "NotExist"
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\NotExist:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
### Catch end###
### Finally###
外部ツールのエラー
PowerShell スクリプトから呼び出した外部ツールでエラーが起きた場合、PowerShell スクリプトではエラーを捕捉できない。try
ブロック内で結果を判定して、期待した結果でなければ throw
すると、その例外を捕捉できる。外部プロセスの結果は $LastExitCode
に書き込まれるので、この値を見て結果を判定できる。具体的な方法は外部ツールによって異なる。