[ PowerShell ] C# / VB.NET から コマンドレットを実行する ( System.Management.Automation )

Pocket

ここでは、C# や VB.NET から PowerShell のコマンドレットを実行するサンプルを掲載しています。

スポンサーリンク

 PowerShell 参照設定の追加

PowerShell を C# や VB.NET から扱うようにするには System.Management.Automation.dll を参照設定に追加する必要があります。多少古い情報ですが、Visual Studio 2008 std. と VS 2010 Express がインストールされている環境では、以下のフォルダに DLL ファイルが存在していました。

C:\Program Files\Reference Assemblies\Microsoft\WindowsPowerShell\v1.0

参照設定の追加を行った後は、VB.NET では Import、C# では using で読み込めば PowerShell をプログラムから扱うことができるようになります。

VB.NET

Imports System.Management.Automation

C#

using System.Management.Automation;

C# から PowerShell コマンドレットを実行する

C# から PowerShell スクリプトを実行するにはいくつか方法があると思いますが、ここでは PowerShell 2.0 から 使用可能になった PowerShell クラスを使用してスクリプトを実行しています。詳細はコメントを参照ください。

C#

    // Runspace を作成する
    using (Runspace rs = RunspaceFactory.CreateRunspace())
    {
        // Runspace をオープンする
        rs.Open();

        using (PowerShell ps = PowerShell.Create())
        {
            PSCommand pscmd = new PSCommand();

            // IPが有効なネットワークアダプタを取得するスクリプト
            string script = @"Get-WmiObject Win32_NetworkAdapterConfiguration | select-object caption,Description, IPEnabled, IPAddress, DHCPEnabled, DefaultIPGateway,MacAddress | where-object {$_.IPEnabled -eq 'True'}";

            pscmd.AddScript(script);
            ps.Commands = pscmd;
            ps.Runspace = rs;

            // スクリプトを実行する
            Collection<PSObject> adapts = ps.Invoke();

            foreach (PSObject adpt in adapts)
            {
                string adptName = adpt.Properties["caption"].Value.ToString();
                string macAddr = adpt.Properties["MacAddress"].Value.ToString();
                string dhcp = adpt.Properties["DHCPEnabled"].Value.ToString();

                // IPアドレスやゲートウェイは配列で返される。
                // (IPv4/v6アドレスなど複数持つ場合があるため)
                string[] ipAddrs = (string[])adpt.Properties["IPAddress"].Value;
                string[] gateways = (string[])adpt.Properties["DefaultIPGateway"].Value;
            }
        }
    }

パラメータをつけてコマンドレットを実行する

C# からコマンドレットにパラメータをつけて実行するサンプルです。上記の PSCommand.AddScript メソッドを 使用するのではなく PSCommand.AddCommandPSCommand.AddParameter メソッドを使用しています。

C#

    // Runspace を作成する
    using (Runspace rs = RunspaceFactory.CreateRunspace())
    {
        // Runspace をオープンする
        rs.Open();

        using (PowerShell ps = PowerShell.Create())
        {
            PSCommand pscmd = new PSCommand();

            // Cドライブ直下のテキストファイルを取得する
            // Get-ChildItem -Path C:\* -Include *.txt を実行する
            pscmd.AddCommand("Get-ChildItem");

            pscmd.AddParameter("Path", @"E:\*");
            pscmd.AddParameter("Include", @"*.txt");

            ps.Commands = pscmd;
            ps.Runspace = rs;

            // スクリプトを実行する
            Collection<PSObject> adapts = ps.Invoke();

            foreach (PSObject file in files)
            {
                // 何か処理を行う
            }
        }
    }

本サンプルでは PSCommand.AddScript メソッドを使って実行する方法と比べて面倒なだけと思うかもしれませんが、PSCommand.AddCommandPSCommand.AddParameter メソッドが威力を発揮するのは、パラメータの値が文字列ではなくオブジェクトの場合です。 例えば、1つ目のコマンドで返されるオブジェクトを一時的に保持して別のコマンドのパラメータに セットして実行する場合に有用です。PSCommand.AddParameter メソッドの第2パラメータ は object 型ですので文字列である必要はありません。

C# からコマンドレットの実体(クラス)を直接呼出し実行する

コマンドレットの実体は、Cmdlet クラスや PSCmdlet を継承して作成されているクラスです。
「 Microsoft.PowerShell.Commands Namespace 」 でコマンドレット ( PowerShell2.0 ) とその実クラスの対応表を確認することができます。

下記に各コマンドレットクラスを直接 C# から操作するサンプルを示してあります。詳細はコメントを参照ください。

C#

// 参照設定も必要になるので、注意すること
using System.Management.Automation;   // Windows PowerShell assembly.
using Microsoft.PowerShell.Commands;  // Windows PowerShell assembly.
using System.Diagnostics;
using System.ServiceProcess;

    // プロセスの一覧を取得する(Get-Process コマンドレット)
    GetProcessCommand gp = new GetProcessCommand();
    gp.Name = new string[] { "[a-c]*" };
    foreach (Process proc in gp.Invoke<Process>())
    {
        Console.WriteLine(proc.ProcessName);
    }

    // サービスの一覧を取得する(Get-Service コマンドレット)
    GetServiceCommand gs = new GetServiceCommand();
    foreach (ServiceController svc in gs.Invoke<ServiceController>())
    {
        Console.WriteLine(svc.ServiceName);
    }

    // イベントログの一覧を取得する(Get-EventLog コマンドレット)
    // 以下を実行すると例外が発生する
    //       [PSCmdlet から派生したコマンドレットは直接呼び出せません。]
    GetEventLogCommand gel = new GetEventLogCommand();
    gel.LogName = "System"; // システムログを出力
    
    foreach (EventLogEntry el in gel.Invoke<EventLogEntry>())
    {
        Console.WriteLine(el.Message);
    }

コメントにもあるように、システムログを出力する際に例外が発生します。 これは、GetEventLogCommand クラスは PSCmdlet クラスを継承して作られているためです。 PSCmdlet クラスを継承しているクラスは C# から直接クラスを操作することができません。前述のサンプルのように PowerShell.Invoke メソッドなどでコマンドレットを実行する必要があります。

スポンサーリンク


Pocket

Leave a Comment

Your email address will not be published. Required fields are marked *