PowerShellの最大の特徴と言われた時に、おそらく掲げるべきはパイプラインだと思います。
それが、cmdやLinux/UNIXシェルにおけるパイプラインと異なる挙動だったり、オブジェクトを伝搬するという性質も含めて良くも悪くもPowerShellをPowerShell足らしめているのはパイプラインかなと。
さて、パイプラインが特徴のPowerShellですが、問題がいくつかあります。その1つが、以下の記事にあるパイプラインの中断処理。
今回は少しその辺をみてみましょう。
StopUpstreamCommandsException
先に結論だけ書くと、InternalなクラスであってもSystem.Management.Automation.StopUpstreamCommandsException
が一番楽ちんでしょう。
ということで、PowerShell版で書くなら雑にこんな感じで。あえてNew-Object
ではなくNew-Object
しています。
中でSystem.Collections.Queue
を使ってるのはそれほどの意味はありません。入力されたオブジェクトをいいように扱うためです。なので、カウンタ変数を用意してでもお好きなようにやればいいと思います。
この方式なら、Cmdletでも同様なので好きなように扱えるのもいいでしょう。
はじめは、ReferenceSource見て自分で実装するのでいいんじゃないかなと思いましたが、当然ながら面倒さが上回ったのでやめました。
仕様変更あったらどうしよう
そもそもその場合は、Select-Object
も仕様変わります。もはやその時点で一緒かなと。
Select -Fist 1のGetSteppablePipeline()
でもPowerShellスクリプトならいいのですが、CmdletからPowerShell関数呼ぶの悲しさしかないですし仕方ないのかなという妥協もあります。
Connect
ちなみにこのInternal ClassなやつをPublicにしてというリクエストはあります。ワークアラウンドにdo{}while()
やdo{}while()
の例もあります。
すでにPowerShellのフィードバックは、UserVoiceに移っており、同フィードバックも転載されています。
なので、Stop-Pipeline
CmdletやStop-Pipeline
のパブリック化がこれに基づきされてほしいですね。Voteしましょう。
Endが実行されないのも、フィードバックすればいいと思います。Endで何かしらするのはリソース破棄以外にもあり得るので、実際あってほしいでしょう。PowerShell Teamの書くスクリプトの中にもProcess{} 句で配列にまとめてEnd{} 句で出力するパターンもあるので。
余談
こういったパイプラインの制限というか、まだまだいけてないシーンはあって、たとえばforeach(){} | ....
もそれです。
パイプラインの中断エラーをWrite-Error
で出せるようにとかもあります。
昔記事にした| Out-Null
の遅さなども。
あとは、Where-Object
などでWhere-Object
抜きで自動変数 $_ にアクセスしたいという例など。実際これほしいですよね。
まとめ
リフレクション最高 (