先日
の続き。
流れは以下のようになるはず
- RunspaceConfigurationインスタンスに関数を登録
- そのインスタンスを引数にRunspaceFactory.CreateRunspace()でRunspaceインスタンスを生成
- Runspace.Open()
- Runspace.CreatePipeline()で関数を呼ぶ
- このPipelineインスタンスにCommands.Add()メソッドでコマンドを入れる
- PipelineインスタンスのInvoke()メソッドを呼んで実行
- RunspaceインスタンスのClosePipeline()を呼んで終了
が、動かない^^;
まずRunspaceConfigurationインスタンスに関数を登録する方法が不明。とりあえずこれは棚上げにして、引数なしでRunspaces.RunspaceConfiguration.Create()を呼び、インスタンスを生成。
次にPipeline.Commands.Add()メソッドは、cmdletまたはcmdletをパイプで繋いだものしか受け付けてくれないこと。つまりPowerShell上で一行づつ入力する形式そのまんまですね。といってもPowerShellで関数定義するように
function add([double]$a,[double]$b){$a+$b}
なんて入れても、次のPipeline.Invoke()の時点でエラーとなり、目論見が外れる。
となると関数はPipelineを作成する前に定義されてなければいけなくなる。それができるのは棚上げにしたRunspaceConfigurationインスタンス。このインスタンスを作成するときに.psc1ファイルを指定可能。これ拡張子が似てますがPowerShellのスクリプトファイルである.ps1とは別物で、試しに上の関数addを定義するだけの.ps1ファイルを指定したら、XML形式じゃないと怒られた。
.psc1ファイルを作成するひとつの方法は、PowerShellでexport-consoleを実行すること。試しに関数addを定義後、
export-console -path .¥test
と打ち込むとこんなファイルができた。
<?xml version="1.0" encoding="utf-8"?>
<PSConsoleFile ConsoleSchemaVersion="1.0">
<PSVersion>1.0</PSVersion>
<PSSnapIns />
</PSConsoleFile>
うん、全く関数addの痕跡なしw このファイルを見る限り、どうやらSnapInのことしか記録してないっぽいです。
SnapInとは特殊な形式のDLLってことで正しいのでしょうか? Visual Studioでプロジェクト作って、PSSnapInを継承したクラスを作ってビルド、これでできたクラスはインストールすればcmdletとして扱われるみたいで、そうすればPipeline.Invoke()で実行できることでしょう。
しかし先日
にも書いたとおり、やりたいのは頻繁に変更される処理だけスクリプト化して柔軟性を増やすことなので、これでは本末転倒。今までスクリプト関数として処理していたものを、cmdletのパイプ繋ぎで実現(必要ならcmdletを作る)できるように考え方を変えないといけないのでしょうね。これ以上調べている時間もなさそうなので、今回もWindows Scripting Controlを使うことになりそうです。
[参考]コマンドレットの作成方法 (C#と諸々)
[2009/3/2 追記] つづき
Comments