C#と諸々

C#がメインで他もまぁ諸々なブログです
おかしなこと書いてたら指摘してくれると嬉しいです(´・∀・`)
つーかコメント欲しい(´・ω・`)

2006/11/28 01:19
【 0. 流れ 】
コマンドレットを作成するにはいくつかの手順を踏む必要がある。大まかな流れは以下のようになる。

1. 準備
2 .NET Fx 2.0 のクラスライブラリとしてコマンドレットを作成する。
3 作成したクラスライブラリをインストールする。
4 PowerShellコンソールにスナップインとして登録する。


【 1. 準備 】
コマンドレットを作成するには、System.Management.Automation.dllというPowerShellのDLLを使用する。
PowerShell をインストールすると、このDLLもインストールされるのだが、このDLLはGACにインストールされる。GACにインストールされているDLLをVisual Studioで参照設定することはできない。また、GACから別のフォルダにアセンブリを移動したりコピーすることも通常はできない。
ではどうやってこのDLLを入手するかというと、Windows SDKをインストールすれば手に入る。Windows SDKをインストールすると、以下のフォルダにPowerShell用の各DLLが配置される。

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

また、Windows SDKをインストールせずとも、手っ取り早く取得する方法もある。PowerShellを使ってGACにインストールされているアセンブリをコピーするという方法である。

[void] (New-Item -path $PSHome -itemType "directory" -name "SDK");
[System.AppDomain]::CurrentDomain.GetAssemblies() | Where {$_.FullName -like "*Version=1.0.0.0*";} | Copy-Item -path {$_.Location;} -destination ($PSHome + "\SDK");


このコマンドを実行すると、PowerShellのインストールフォルダ ( 通常はC:\Windows\system32\windowspowershell。 ) に、SDKというフォルダが作成され、そこにPowerShell用のアセンブリが配置される。 ( 配置先のパスは全く別の場所でも構わない。 )
この方法なら、わざわざWindows SDKをダウンロード&インストールする必要がない。特に理由がなければこの方法で充分である。



【 2 コマンドレットの作成 】

[ 2.1 プロジェクトの作成 ]
Visual Studio 2005にて、クラスライブラリプロジェクトを新規作成し、以下の2つのDLLを参照設定に追加する。

System.Management.Automation.dll
System.Configuration.Install.dll


[ 2.2 スナップインクラスの作成 ]
スナップインクラスによって、インストールスナップイン登録が可能となる。スナップインクラスは、一つのコマンドレットクラスライブラリに一つだけ用意する。

2.2.1 スナップインクラス
スナップインクラスは、PSSnapIn クラス (System.Management.Automation)の派生クラスとして作成する。  ( PSSnapInクラスは、Installer クラス (System.Configuration.Install)を継承している。 )
また、スナップインクラスにはRunInstallerAttribute クラス (System.ComponentModel)を属性として付加する。その際、属性の引数にはTrueを指定する。

PSSnapInクラスには以下の3つの抽象プロパティが用意されているので、これを実装する必要がある。

Nameプロパティ ( public abstract string Name { get; } )
スナップインの名称。
Venderプロパティ  ( public abstract string Vender { get; } )
スナップイン製作者の名称。
Descriptionプロパティ ( public abstract string Description { get; } )
スナップインの説明文。


2.2.2 実装例using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using System.Management.Automation;

namespace YokoKen.PowerShell.Test
{
    [RunInstaller(true)]
    public class TestPSSnapIn : PSSnapIn
    {
        public override string Name
        {
            get
            {
                return "YokoKen.PowerShell.Test";
            }
        }

        public override string Vendor
        {
            get
            {
                return "YokoKen";
            }
        }

        public override string Description
        {
            get
            {
                return "この Windows PowerShell スナップインには、コマンドレット開発テスト用のコマンドレットが含まれています。";
            }
        }

        public TestPSSnapIn() : base()
        {
        }
    }
}


[ 2.3 コマンドレットクラスの作成 ]
コマンドレットはクラスとして実装する。一つのコマンドレットクラスで、一つのコマンドレットとなる。コマンドレットクラスは一つのクラスライブラリに複数作成することができる。

2.3.1 コマンドレットクラス
コマンドレットクラスは、Cmdlet クラス (System.Management.Automation)の派生クラスとして作成する。
また、コマンドレットクラスにはCmdletAttribute クラス (System.Management.Automation)を属性として付加する。その際、属性の引数には以下の2つを指定する必要がある。

verbName ( String型 )
コマンドレットの名称の動詞部分。
nounName ( String型 )
コマンドレットの名称の名詞部分。


2.3.2 コマンドレットのパラメータ
コマンドレットのパラメータは、コマンドレットクラスのプロパティとして実装する。パラメータとするプロパティには、setterを用意し、ParameterAttribute クラス (System.Management.Automation)を属性として付加する。属性にはいくつかの名前付き引数が用意されているが、以下の3つは特に重要である。

Mandatory ( Boolean型 )
コマンドレットを実行する際の必須パラメータかどうかを示す値。
Position ( Int32型 )
コマンドレットを実行する際のパラメータの ( 0から始まる ) 順番。
ValueFromPipeline ( Boolean型 )
パラメータの値をパイプラインから受け取ることができるかどうかを示す値。


2.3.3 コマンドレットの処理を実装
Cmdletクラスにはいくつかの仮想メソッドが用意されている。コマンドレットの処理は、この仮想メソッドをオーバーライドして実装する。主な仮想メソッドは以下の4つ。

BeginProcessingメソッド
事前処理を行うためのメソッド。「パイプラインで配列が渡されたためにコマンドレットが一度に複数回実行される」といった場合でも、このメソッドは最初に一度だけしか実行されない。
ProcessRecordメソッド
処理を行うためのメソッド。
EndProcessingメソッド
事後処理を行うためのメソッド。「パイプラインで配列が渡されたためにコマンドレットが一度に複数回実行される」といった場合でも、このメソッドは最後に一度だけしか実行されない。
StopProcessingメソッド
コマンドレットの実行中にCtrl+Cが押下された場合に実行されるメソッド。

なお、コマンドレットの実行中にCtrl+Cの押下によって処理が中断された場合、CmdletクラスのStoppingプロパティがTrueに設定される。中断されても、そのとき実行されていたメソッドは最後まで処理が行われる。ただし、Ctrl+Cによる中断が行われると、一時的にコンソールへの出力が無効となる。(よって、StopProcessingメソッド内でのコンソール出力処理は無意味。)


2.3.4 実装例using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;

namespace YokoKen.PowerShell.Test.Commands
{
    [Cmdlet("Out", "Hoge")]
    public class OutHogeCommand : Cmdlet
    {
        private int count;

        [Parameter(Mandatory = true, Position = 0)]
        public int Count
        {
            get
            {
                return this.count;
            }
            set
            {
                if (value < 0)
                {
                    throw new ArgumentOutOfRangeException("Count", "Countに負の値を設定することはできません。");
                }
                this.count = value;
            }
        }

        public OutHogeCommand() : base()
        {
            this.count = 0;
        }

        protected override void ProcessRecord()
        {
            StringBuilder outputBuilder = new StringBuilder();
            for (int i = 0; i < this.count; i++)
            {
                outputBuilder.Append("Hoge");
            }
            this.WriteObject(outputBuilder.ToString());
        }
    }
}


【 3. インストール 】
作成したクラスライブラリは、インストーラ ツール (Installutil.exe)を使って、インストールする必要がある。

PowerShellのインストールフォルダ内にSnapInというフォルダを作成し、そこに配置した"YokoKen.PowerShell.Test.dll"というアセンブリをインストールする場合、以下のようなコマンドになる。

&"$env:windir/Microsoft.NET/Framework/v2.0.50727/InstallUtil.exe" ($PSHome + "\SnapIn\YokoKen.PowerShell.Test.dll");


インストール後にクラスライブラリを別の場所に移動したり削除してはいけないことに注意。なお、クラスライブラリの配置場所は上記の例とは全く別の場所でも構わない。


【 4. スナップイン登録 】
インストールまで完了したら、あとはコンソールへのスナップイン登録のみである。
スナップイン登録は、Add-PSSnapinコマンドレットのnameパラメータにスナップインの名前を指定して実行するだけでできる。スナップインの名前とは、スナップインクラスに実装したNameプロパティが返す値である。
2.2.2 実装例のコードでは、Nameプロパティが"YokoKen.PowerShell.Test"という値を返すように実装した。この場合は以下のように"YokoKen.PowerShell.Test"を指定する。

Add-PSSnapin "YokoKen.PowerShell.Test";


これでコマンドレットが使用できるようになった。
なお、スナップイン登録は、PowerShellの起動のたびに行う必要がある。これが面倒な場合は、profile.ps1 を利用するという手がある。スナップイン登録のためのコマンドを profile.ps1 に記述しておくことにより、起動時に自動で実行される。 ( profile.ps1 については PowerShell 付属の「Windows PowerShell™ ファースト ステップ ガイド」を参照。 )


【 5. 実行 】
Out-Hoge 5; ってコマンドを実行すれば"HogeHogeHogeHogeHoge"って出力される。


【 6. 参考 】
Windows PowerShell SDK
System.Management.Automation Namespace
Web ChangeLog: MSH: Using MshSnapIn
Writing an useful cmdlet for Windows PowerShell - The Code Project - Vista / .NET 3.0
getting started with SDK in microsoft.public.windows.powershell


【 追記 】
余談ですが、コマンドレットは実行ファイル形式のアセンブリでも問題なく作れたりもします。
タグ: .NET PowerShell











トラックバックURL↓
http://csharper.blog57.fc2.com/tb.php/55-716fec12

[PowerShell] time コマンドのようなコマンドレット
PowerShell で、あるコマンドの実行時間を測定するためには、Measure-Command というコマンドレットが使えます。PS &gt; Measure-Command { Get-ChildItem C:\Windows -filter &quot;*.

2007.07.18 23:05 | Bear's Droppings