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 に書き込まれるので、この値を見て結果を判定できる。具体的な方法は外部ツールによって異なる。