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