上記の記事を書いてから、あまり良いプラクティスとは思えなくなって、結局実際仕事で書いてるソースコードの方も上記の記事の書き方はやめてたりする。
なぜかと言うと出力を出さない事で、
- ブロック内のデバッグが恐ろしくし辛い
- ブロック内でエラー出ても出力されない
という非常にまずい書き方だというのが分かったため。
まぁ少し考えれば分かりますね…
代わりにどう書いてるかと言うと、関数内の出力はそのままで、「関数の終了コード」に当たるものは戻り値で受け取るのではなく「$global:LASTEXITCODE」を参照する事にした。
この方がややこしくないしずっと直感的ですね。
function func {
...
}
func
if ($global:LASTEXITCODE -ne 0) {
# 例外処理
}
余談
ちなみにコマンドレットとそうでない外部コマンドとで、$LASTEXITCODEと$?が設定されるか否かが違うのって地味にハマりますね。
function func {
...
}
Move-Item $src $dest
if ($global:LASTEXITCODE -ne 0) {
# $LASTEXITCODEはセットされないのでエラーが起きてもここには来ない。
}
if ($? -eq $False) {
# $? を見るか、もしくはコマンドレットの引数に
# -ErrorAction Stopを付けてtry catchで囲むかする必要がある。
}
表にするとこんな感じ。
| 種類 | コマンドレット | それ以外のコマンド |
|---|---|---|
| $LASTEXITCODE | セットされない | セットされる |
| $? | セットされる | セットされる |
まぁシェルスクリプトにもシェルの内部コマンドだったりエイリアスだったり外部コマンドだったりあるのでPowerShellよりずっと複雑なように思えるけど、そんな事はなくて戻り値は一貫して$?で取れるので、困るのって上記の種類が違う同名のコマンドが定義されてた場合にどれが起動されるかでハマる位でその他ハマる点ってないんですよね。
なので正直PowerShellには戻り値のインターフェースぐらい統一してほしい感がありますね…