PowerShell スクリプト式をC#から実行する

自宅に居さえすれば何していたっていいんだよな。つーことで。

話題にしたWindows PowerShellだが、思惑通りにDIの評価式に使うには、.NETプラットホームの言語中、具体的にはC#等から比較的簡単にスクリプト式を実行することができて、尚且つ結果を取得できなくてはならない訳で、できるかどうか早速試してみた。

最新のRC1パッケージをインストールするだけ。(要.NET Framework 2.0)
Download Windows PowerShell Release Candidate

インストールしたパッケージのディレクトリには以下の.NETアセンブリが含まれていた。

Microsoft.PowerShell.Security.dll
Microsoft.PowerShell.ConsoleHost.dll
Microsoft.PowerShell.Commands.Utility.dll
Microsoft.PowerShell.Commands.Management.dll
System.Management.Automation.dll

このうち、単純なスクリプトの実行に使用するのはSystem.Management.Automation.dllだけのようだ。早速簡単なアプリケーションを書いてみよう。

using System;
using System.Management.Automation;
namespace PowerShellInvokeTest {
    class Program {
        static void Main(string[] args) {
            try {
                RunspaceInvoke invoker = new RunspaceInvoke();

                //PowerShellでDateTime.Nowを取得
                string script = "[DateTime]::Now";
                object result = invoker.Invoke(script)[0].BaseObject;
                Console.WriteLine(result);

                //PowerShellでSizeオブジェクトを生成
                script = "new-object System.Drawing.Size(100, 100)";
                result = invoker.Invoke(script)[0].BaseObject;
                Console.WriteLine(result);

                //PowerShellでFormオブジェクトを生成して表示
                script = "new-object System.Windows.Forms.Form";
                result = invoker.Invoke(script)[0].BaseObject;
                (result as System.Windows.Forms.Form).Show();
            } finally {
                Console.WriteLine("Press any key to exit...");
                Console.ReadKey();
            }
        }
    }
}

スクリプトの実行と結果の取得はRunspaceInvokeクラスのインスタンスのInvokeメソッドにパラメタとしてスクリプト式を渡すだけであり、非常に簡単であることが判る。スクリプトの実行結果はCollectionという型のGenericsコレクションで戻るため、実際の結果オブジェクトを取得するためには、インデクサ経由でPSObjectを取得してPSObjectのBaseObjectプロパティを取得すればよい。

object result = invoker.Invoke(script)[0].BaseObject;

以下、実行した結果のスクリーンショット

PowerShellによって生成されたSystem.Windows.Forms.Formクラスのインスタンスに対して実行したShowメソッドも成功しているのが判る。

PowerShell自体が.NETで作られていることからして、.NET Frameworkへのアクセスには制限は無い訳で、式評価エンジンとして使うには、かなりいいかもしれない。

Expression Evaluation for DIContainer

seasar2は設定ファイル上の評価式をOGNL式から評価して、結果をインジェクションすることが可能だが、これが非常に強力な機能となっている。(と私は思う) となると、.NETのDIコンテナでも当然評価式をインジェクションしたいのだが、残念ながらOGNLの.NET(CLI)実装は存在していない。従って、s2dotnetは.NETのCodeProviderを利用してJavascriptのEvalによる評価式を使うようになっている訳だ。(OGNLの.NET実装は存在しているぞ!、という方は是非教えて欲しい) ならばSpring.NETは何を使っているのかと調べてみると、どうやらANTLRがベースのようだ。

The expression language is based on a grammar and uses ANTLR to construct the lexer and parser. Errors relating to bad syntax of the langage will be caught at this level of the language implementation. 〜
http://www.springframework.net/doc/reference/html/expressions.html

うーん、Spring.NETと同じってのもなんだし、もっと.NETの特徴を生かせるものはないのかと思っていたのだが、実は有力な候補があるではないか、と。

Windows PowerShell / Micosoft Technology Centers

少し前まで"Monad"とか"MSH"などと呼ばれていた、Windowsの次世代のシェル。.NET Frameworkの全てにアクセス出来て、.NETアプリケーションからホストすることも出来るらしい。
Windows PowerShellの式評価が.NETアプリケーションから出来るならば、例えばDateプロパティに現在の日付をインジェクションし、Sizeプロパティに100×100のSizeオブジェクトをインジェクションする場合、以下のように書けることだろう。

<property name="Date">[DateTime]::now</property>
<property name="Size">new-object System.Drawing.Size(100, 100)</property>

(XMLじゃ使えない文字も使えたりするんで、[CDATA]セクションで括る必要があるかも)
現時点では妄想でしか無いけれど(PowerShellもまだRC1だったり、WindowsXP以降限定だったりする)、OGNLの実装に時間がかかるのであればこれもありではないかと。