PowerShell でホストプログラムとの通信を行う


自動変数は、色々ありすぎて個別に解説が必要になろうものですが、逆に言えば色々なところに情報があるので、設定変数と同様に1つだけを例として取り出すことにします。
今回取り扱うのは、$Host 自動変数です。スコープの話で少し触れましたが、PowerShell の実行環境は RunSpace という単位になっており、自作のアプリケーションでも RunSpace を生成してスクリプトを流し込むだけで PowerShell を内蔵したアプリケーションを作ることができます。*1 *2 RunSpace の内側で動いている PowerShell から RunSpace の外側にアクセスするためのインターフェースが $Host です。
ホストプログラムに依存した機能は、ホストプログラムが何であるかによって異なる動きをします。標準でついてくるホストプログラムである powershell.exe と PowerShell ISE を動かして次のようなスクリプトを実行してみましょう。ホストプログラムによって Write-Progress コマンドの結果が違うことを確認できます。

PS > &{
    foreach ($i in 0..9)
    {
        Write-Progress "My Action" "Running" -PercentComplete $($i * 10) -SecondsRemaining $(10 - $i);
        Sleep 1;
    }
    Write-Progress "My Action" "Done" -Completed
}

他にも、

PS > $in = Read-Host -Prompt "入力してください";

のようなホストを対象にしたコマンドを実行しても、実行結果が違うことがわかります。Read-Host や Write-Host, Write-Progress といったホスト依存のコマンドはホストプログラムに対する基本操作として PowerShell の RunSpace を生成するために準備することが必要となっている標準的な機能ですが、*3 ホストプログラムによってはホストプログラムに固有の機能を提供するものがあり、そこにアクセスするには $Host のメンバーである UI.RawUI と PrivateData を使用することになります。*4
たとえば、標準の PowerShell コマンドでは Windows のコンソール上で動作するので、コンソールのいくつかの機能を RawUI として公開しています。Get-Member コマンドを使ってどのようなものが公開されているか確認でき、たとえば WindowTitle を自由に変更することができるようになっていて、

PS > $Host.UI.RawUI.WindowTitle = "作業中..."

このような感じで、PowerShell の動いているコンソールウインドウのタイトルを書き換えることができるので、スクリプトの名前や処理状況を表示するなどで活用できます。また、PrivateData にはエラー出力や詳細出力といったアウトプット系の出力に対して PowerShell ホストがどのような色を使用するかを設定することができるようになっています。
ただ、あまり汎用的なスクリプトで $Host を直接使用することは避けたほうがよいでしょう。まだ、PowerShell のメジャーなホストプログラムはあまり数がありませんが、ホストプログラムが切り替わって動かなくなるのはあまり嬉しいことではありません。

*1:多くの場合は、アプリケーションに PowerShell をホストするよりも、アプリケーションにプログラマブルなインターフェースを設けてコマンドレット等を提供するほうが、ユーザが任意のホストを選択できるという利点が生まれて便利だったりします。

*2:PowerShell ISE では、ファイルメニューの「PowerShell タブの新規作成」を選ぶと、1つの PowerShell ISE 上に新しい RunSpace を作ることができ、図の MyApp.exe のような形になります。

*3:ホストプログラムが UI を持たない場合など、NotImplementedException や InvalidOperationException といったエラーを返すような場合もありうる。

*4:$Host.UI は基本的な UI 操作を提供しているインターフェースであり、Write-Host 等のコマンドはこの $Host.UI を使用して画面出力などを行っている。