院長のメモ帖
2013年11月 2日 土曜日
PowerShellとC#の連携
最近、PowerShellスクリプトにはまってます。
PowerShellが出始めた当初は、パイプラインの考え方がなかなかなじめず全然使いこなせてませんでした。それというのも最初に買った何冊かの解説本のせいでもあります。いま読み返すと、著者がPowerShellを全く使いこなせずに書いたことが明確に分かってしまうほど内容の薄い本でした。
C#でLINQを使いこなしてからPowerShellの世界に戻ってい見ると、パイプラインの動作も簡単に理解でき、また3.0以降のPowerShellはかなりコマンドも充実してきたこともあり結構な数のスクリプトにサーバー管理を任せるようになりました。
ただ、僕のホームグラウンドはC#でして、だいぶ使い勝手がよくなったとはいえPowerShell IDEとVisual Studioの使い勝手の違いがどうしても気に入りません。また、Powershellの実行結果をグラフィカルに処理しようと思うと、Excelとかを使ってデーターを処理して、それをコマンドに直して実行させたりするのが結構めんどくさいので、C#で直接Powershellをいじれないものかと思ってしらべてみたら、ちゃんとやり方があるんですね。
1) 次のdllをプロジェクトに参照設定する。
C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll
System.Management.Automation
2) コマンド内容を文字列Sourceとして、次のメソッドを使うと結果の列挙が得られる
public static IEnumerable<dynamic> RunCommands(string Source, object[] parameter)
{
using (var invoker = new RunspaceInvoke())
{
System.Collections.ObjectModel.Collection<PSObject> results = invoker.Invoke(Source, parameter);
return results.OfType<dynamic>();
}
}
Powershellの結果は、PSObjectという動的な型にくるまれて帰ってくるので、そのまま使ってもいいのですが、これをDynamicにキャストして置けば、このメソッドを使うソースでは1)のusingを省けるのでキャストしています。プロパティー名さえ分かっていれば、これで必要な結果を取り出すことはできます。
また、PSObject.BaseObjectに元の型のままのオブジェクトが入っているので、元の型情報をdllを参照して用意できるなら、以下のジェネリックメソッドが使えます。
public static IEnumerable<T> RunCommands<T>(string Source, object[] parameter) where T : class
{
using (var invoker = new RunspaceInvoke())
{
System.Collections.ObjectModel.Collection<PSObject> results = invoker.Invoke(Source, parameter);
return results.Select(r => r.BaseObject as T);
}
}
このジェネリック版を使えば、静的なC#の世界にすべてを持ち込めます。
この2つのメソッドで、PowershellでできることがC#から呼び出せるようになったので、グラフィカルな管理ツールを作成してみようかなと思ってます。
この記事は、以下のページを参考にさせていただきました。あわせてお読みください。
++C++;// 未確認飛行 C
PowerShellが出始めた当初は、パイプラインの考え方がなかなかなじめず全然使いこなせてませんでした。それというのも最初に買った何冊かの解説本のせいでもあります。いま読み返すと、著者がPowerShellを全く使いこなせずに書いたことが明確に分かってしまうほど内容の薄い本でした。
C#でLINQを使いこなしてからPowerShellの世界に戻ってい見ると、パイプラインの動作も簡単に理解でき、また3.0以降のPowerShellはかなりコマンドも充実してきたこともあり結構な数のスクリプトにサーバー管理を任せるようになりました。
ただ、僕のホームグラウンドはC#でして、だいぶ使い勝手がよくなったとはいえPowerShell IDEとVisual Studioの使い勝手の違いがどうしても気に入りません。また、Powershellの実行結果をグラフィカルに処理しようと思うと、Excelとかを使ってデーターを処理して、それをコマンドに直して実行させたりするのが結構めんどくさいので、C#で直接Powershellをいじれないものかと思ってしらべてみたら、ちゃんとやり方があるんですね。
1) 次のdllをプロジェクトに参照設定する。
C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll
System.Management.Automation
2) コマンド内容を文字列Sourceとして、次のメソッドを使うと結果の列挙が得られる
public static IEnumerable<dynamic> RunCommands(string Source, object[] parameter)
{
using (var invoker = new RunspaceInvoke())
{
System.Collections.ObjectModel.Collection<PSObject> results = invoker.Invoke(Source, parameter);
return results.OfType<dynamic>();
}
}
Powershellの結果は、PSObjectという動的な型にくるまれて帰ってくるので、そのまま使ってもいいのですが、これをDynamicにキャストして置けば、このメソッドを使うソースでは1)のusingを省けるのでキャストしています。プロパティー名さえ分かっていれば、これで必要な結果を取り出すことはできます。
また、PSObject.BaseObjectに元の型のままのオブジェクトが入っているので、元の型情報をdllを参照して用意できるなら、以下のジェネリックメソッドが使えます。
public static IEnumerable<T> RunCommands<T>(string Source, object[] parameter) where T : class
{
using (var invoker = new RunspaceInvoke())
{
System.Collections.ObjectModel.Collection<PSObject> results = invoker.Invoke(Source, parameter);
return results.Select(r => r.BaseObject as T);
}
}
このジェネリック版を使えば、静的なC#の世界にすべてを持ち込めます。
この2つのメソッドで、PowershellでできることがC#から呼び出せるようになったので、グラフィカルな管理ツールを作成してみようかなと思ってます。
この記事は、以下のページを参考にさせていただきました。あわせてお読みください。
++C++;// 未確認飛行 C
投稿者 美濃加茂市のIT獣医師 近藤 博 | コメント(0)
コメントする