カスタムプロバイダーを作ってみよう その1

PowerShellの重要な特徴として、ファイルシステムレジストリ環境変数など異なるデータソースに対して共通の操作(コマンドレット)が行えるということが挙げられます。

例えば、以下のように「C」ドライブ直下に「New-Item」コマンドレットでファイルを作成できるのと同じ感覚で、

PS c:\> New-Item hoge

「HKLM」ドライブ(HKEY_LOCAL_MACHINE)に移動して、「New-Item」コマンドレットでレジストリキーが作れるといった具合にです。

PS HKLM:\Software > New-Item hoge

これらはプロバイダーという機構によって成り立っています。

ファイルシステムならFileSystemProviderレジストリならRegistryProvider環境変数ならEnvironmentProviderと言った具合にそれぞれに対応するプロバイダーが用意されています。

PowerShellには「New-PSDrive」というコマンドレットが用意されています。
このコマンドレットは「PSDrive」というPowerShell上でだけ有効な仮想的なドライブを新規作成するものですが、このコマンドレットのパラメータを見て下さい。

New-PSDrive [-name] [-psProvider] [-root] [-description ] [-scope ] [-credential ]

二つ目の引数に「psProvider」というのがあります。この引数でどのプロバイダーを使ってPSDriveを作成するかを決めるわけです。

例えばFileSystemProviderを使って、「C:\WINDOWSディレクトリをルートとする「WIN」ドライブを作る場合、以下のようにします。

PS > New-PSDrive WIN FileSystem C:\WINDOWS

Name       Provider      Root
----       --------      ----
WIN        FileSystem    C:\WINDOWS

このようにして、プロバイダーを指定してPSDriveを作成する事ができます。

これらの事からプロバイダーとは、様々な種類のPSDriveを提供するための機構だということがわかります。

開発環境の構築

では、さっそくプロバイダーを作っていきましょう。

開発環境として、

を使用します。

また、プロバイダーの開発には.NET FrameworkC#に対する基本的な知識が必要になります。

開発用のアセンブリをコピー

プロバイダーの開発には、「System.Management.Automation」というアセンブリが必要になりますが、このアセンブリはGACにのみインストールされているので、ここから取り出す必要があります。

GACにインストールされたアセンブリWindows Explorerからはコピーができないので、コマンドプロンプトPowerShellを使ってコピーする必要があります。

「System.Management.Automation.dll」を以下のパスから適当な場所にコピーして下さい。

  • C:\WINDOWS\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Management.Automation.dll

プロジェクトの作成

では、プロバイダーの仕組みを学ぶ為に簡単なプロバイダーを作ってみましょう。

Visual Studio 2008を起動して、言語は「Visual C#」で「クラスライブラリ」プロジェクトを作成します。プロジェクト名は「PSHoge」とします。

まずは先程コピーした「System.Management.Automation.dll」アセンブリを参照設定に追加しておきます。

では、プロバイダーを作ってみましょう。

プロバイダーはCmdletProviderクラスを継承して作ります。
しかし、CmdletProviderには必要最低限の機能しか実装されていないので、ここからプロバイダーを実装するのは結構大変です。

なので、通常はCmdletProviderから派生したNavigationCmdletProviderを使用します。

CmdletProviderNavigationCmdletProviderなどとの継承関係を以下に示します。

プロバイダークラスの継承ツリー
  • CmdletProvider
    • DriveCmdletProvider
      • ItemCmdletProvider
        • ContainerCmdletProvider
          • SessionStateProviderBase
            • AliasProvider
            • EnvironmentProvider
            • FunctionProvider
            • VariableProvider
          • NavigationCmdletProvider
            • FileSystemProvider
            • RegistryProvider

ファイルシステムレジストリNavigationCmdletProviderから、環境変数エイリアスSessionStateProviderBaseから派生しているのがわかります。

では、NavigationCmdletProviderを継承してプロバイダークラスを作ります。

「HogeProvider.cs」というファイル名でクラスファイルを追加します。

HogeProvider.cs
using System;
using System.Management.Automation.Provider;

namespace PSHoge {
     [CmdletProvider("Hoge", ProviderCapabilities.ShouldProcess)]
     public class HogeProvider : NavigationCmdletProvider {

         protected override bool IsValidPath(string path) {
             return true;
         }

     }
}

NavigationCmdletProviderクラスを継承して、IsValidPathメソッドをオーバーライドします。ここではとりあえずtrueを返しておきます。

そして、プロバイダークラスである事を示す為にCmdletProvider属性でマークしています。引数として「Hoge」と「ProviderCapabilities.ShouldProcess」を渡しています。

前者はプロバイダー名で後者はとりあえずこれを指定しておいて下さい。

次にこのプロバイダーをPowerShellにインストールするためのインストーラクラスを作成します。

HogeSnapIn.cs
using System;
using System.Management.Automation;
using System.ComponentModel;

namespace PSHoge {
     [RunInstaller(true)]
     public class HogeSnapIn : PSSnapIn {

         public override string Description {
             get { return "テスト用のプロバイダーです。"; }
         }

         public override string Name {
             get { return "Hoge"; }
         }

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

PowerShellインストーラクラスはPSSnapInクラスから派生させます。DescriptionNameVendorというプロパティをそれぞれ実装する必要があります。

そして、このクラスがインストーラクラスである事を示す為にRunInstaller属性でマークしておきます。
とりあえずここまでで一度PowerShellにこのプロバイダーをインストールしてみましょう。

プロジェクトをビルドして、プロジェクトの出力ディレクトリ(bin\Debug)にコマンドプロンプトで移動して下さい。

以下のコマンドを実行してプロバイダーをインストールします。

PS > InstallUtil.exe PSHoge.dll

正常にインストールが完了したらPowerShellを起動して以下のコマンドを実行します。

PS > Add-PSSnapin Hoge

これでPowerShellにプロバイダーのインストールが完了しました。

あとは前述の「New-PSDrive」コマンドレットを使って、ドライブを新規作成します。

PS > New-PSDrive Hoge Hoge c:\

これで「Hoge」プロバイダーで「Hoge」ドライブを作る事ができました。ルートディレクトリのパスはここでは意味はありませんが、指定する必要があります。

では、試しに「Hoge」ドライブにcdしてみましょう。

Set-Location : プロバイダがこの操作をサポートしていないため、プロバイダの実行が中止されました。
発生場所 行:1 文字:3
+ cd  <<<< hoge:

実はこの段階ではまだcdはできません。では次はこれができるようにしてみましょう。