2006-01-22

MSH: Using MshSnapIn

Beta 3 で導入された MshSnapIn を使うと、msh.exe の実行中にコマンドレットのアセンブリを追加することができます。Beta 2 の MSH では、C# で開発したコマンドレットを追加するにはいちいち make-shell コマンドを使って新たなカスタム MSH シェルを作成する必要がありました。Beta 3 でもカスタムシェルの作成は可能で、シェルを拡張したい場合などの特定の用途向けに有効な手段です。ただし、MshSnapIn が作成できるのは msh.exe を利用する場合のみで、完全なマネージドコードによるカスタムシェルで MshSnapIn を利用することはできません。

実装

以下に紹介するのは MD5 ダイジェストを生成する GetDigestCommand コマンドレットを実装する例です。このコマンドレットは C# で作成しますが、これを msh.exe に登録するために、 MshSnapIn のサブクラスを実装する必要があります。これらの2つのクラスを実装したものが以下です:

using System;
using System.ComponentModel;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Management.Automation;

namespace MonadUtility
{
    [RunInstaller(true)]
    public class MonadUtilityMshSnapIn : MshSnapIn
    {
        /// <summary>Creates an instance of MshSnapIn class.</summary>
        public MonadUtilityMshSnapIn()
            : base()
        {
        }
        ///<summary>The snapin name which is used for registration</summary>
        public override string Name
        {
            get
            {
                return "MonadUtilityMshSnapIn";
            }
        }
        /// <summary>Gets vendor of the snapin.</summary>
        public override string Vendor
        {
            get
            {
                return "Mitsuru Oka";
            }
        }
        /// <summary>Gets description of the snapin. </summary>
        public override string Description
        {
            get
            {
                return "This MshSnapIn has a cmdlet to handle MSI installer file.";
            }
        }
    }
}

namespace MonadUtility.Commands
{
    [Cmdlet("Get", "Digest", DefaultParameterSetName = "InfoSet")]
    public class GetDigestCommand : Cmdlet
    {
        internal bool fileInfoSpecified = false;
        internal FileInfo fileInfo = null;
        internal bool fullNameSpecified = false;
        internal string fullName = null;

        [Parameter(Position = 0, ParameterSetName = "InfoSet",
                   ValueFromPipeline = true)]
        public FileInfo FileInfo
        {
            get { return fileInfo; }
            set { fileInfo = value; fileInfoSpecified = true; }
        }

        [Parameter(Position = 0, ParameterSetName = "NameSet",
                    ValueFromPipelineByPropertyName = true)]
        public string FullName
        {
            get { return fullName; }
            set { fullName = value; fullNameSpecified = true; }
        }

        protected override void ProcessRecord()
        {
            if (fileInfoSpecified)
            {
                string digest = GetMD5Digest(FileInfo.FullName);
                WriteObject(digest);
            }
            else if (fullNameSpecified)
            {
                string digest = GetMD5Digest(fullName);
                WriteObject(digest);
            }
        }

        private string GetMD5Digest(string filePath)
        {
            using (Stream inputStream =
                new FileStream(filePath, FileMode.Open, FileAccess.Read))
            {
                byte[] bytes =
                    new MD5CryptoServiceProvider().ComputeHash(inputStream);
                string digest = BitConverter.ToString(bytes);
                return digest;
            }
        }
    }
}

ビルド

以下のように MSH 上で、上記の MonadUtility.cs ファイルをコンパイルします。

MSH> $ref = "$MSHHOME/System.Management.Automation.dll"
MSH> $compiler = "$env:windir/Microsoft.NET/Framework/v2.0.50727/csc"
MSH> &$compiler /target:library /r:$ref MonadUtility.cs

インストール

アセンブリをインストールします。

MSH> $installutil = "$env:windir/Microsoft.NET/Framework/v2.0.50727/InstallUtil.exe"
MSH> &$installutil -i MonadUtility.dll

ちなみにアセンブリがインストールされたことを以下のように確認できます:

MSH> get-mshsnapin -registered


Name        : CommandUtilityMshSnapIn
MshVersion  : 1.0
Description : This MshSnapIn has a cmdlet to handle MSI installer file.

登録

インストールされたアセンブリに含まれるコマンドレットを現在の msh.exe シェルに追加します。

MSH> add-mshsnapin MonadUtilityMshSnapIn

シェルにアセンブリが追加されたことを以下のように確認できます:

MSH> get-mshsnapin
...
Name        : MonadUtilityMshSnapIn
MshVersion  : 1.0
Description : This MshSnapIn has a cmdlet to handle MSI installer file.

読み込まれたアセンブリ内のコマンドレットを実行してみます:

MSH> dir


    Directory: Microsoft.Management.Automation.Core\FileSystem::C:\Documents an
    d Settings\oka326\My Documents\Foods


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2005/12/24     15:31      39779 DaoxiaomianMap.html
-a---        2005/12/24     15:31      13700 DaoxiaomianMap.xml
-a---        2005/11/27      3:13        264 LaunchMap.js


MSH> dir |get-digest
9F-D4-22-27-3C-0E-52-02-CE-9F-1A-3D-51-38-B5-F3
2B-3A-4B-02-A2-72-A4-FB-46-91-C6-C0-63-93-72-69
51-0A-BB-86-9F-15-27-56-DC-2F-42-1D-26-F9-DC-52

設定を残す

自分の profile.msh に add-mshsnapin MonadUtilityMshSnapIn を追加すれば、msh.exe 起動時にこのスナップインアセンブリを追加するともできますが、それ以外にも、今の msh.exe の状態を残しておいて、起動時に設定を読み込む方法があります:

MSH> export-console MonadUtility

こうすると、MonadUtility.mcf ファイルが作成され、今読みこまれているスナップインアセンブリのリストが作成されます。msh.exe に以下のような引数を渡せば、起動時にこのスナップインアセンブリを読み込みます:

msh -MshConsoleFile  MonadUtility.mcf

この方法を使えば、ショートカットごとに起動する MSH の構成を変更することもできるでしょう。

0 コメント: