カスタムプロバイダーを作ってみよう その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を提供するための機構だということがわかります。
開発環境の構築
では、さっそくプロバイダーを作っていきましょう。
開発環境として、
- PowerShell 1.0
- Microsoft Visual Studio 2008 Standard Edition (Visual C# 2008 Expressでも可)
を使用します。
また、プロバイダーの開発には.NET FrameworkとC#に対する基本的な知識が必要になります。
開発用のアセンブリをコピー
プロバイダーの開発には、「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を使用します。
CmdletProviderとNavigationCmdletProviderなどとの継承関係を以下に示します。
プロバイダークラスの継承ツリー
- CmdletProvider
- DriveCmdletProvider
- ItemCmdletProvider
- ContainerCmdletProvider
- SessionStateProviderBase
- AliasProvider
- EnvironmentProvider
- FunctionProvider
- VariableProvider
- NavigationCmdletProvider
- FileSystemProvider
- RegistryProvider
- SessionStateProviderBase
- ContainerCmdletProvider
- ItemCmdletProvider
- DriveCmdletProvider
ファイルシステムやレジストリは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クラスから派生させます。Description、Name、Vendorというプロパティをそれぞれ実装する必要があります。
そして、このクラスがインストーラクラスである事を示す為にRunInstaller属性でマークしておきます。
とりあえずここまでで一度PowerShellにこのプロバイダーをインストールしてみましょう。
プロジェクトをビルドして、プロジェクトの出力ディレクトリ(bin\Debug)にコマンドプロンプトで移動して下さい。
以下のコマンドを実行してプロバイダーをインストールします。
PS > InstallUtil.exe PSHoge.dll
PS > Add-PSSnapin Hoge
あとは前述の「New-PSDrive」コマンドレットを使って、ドライブを新規作成します。
PS > New-PSDrive Hoge Hoge c:\
では、試しに「Hoge」ドライブにcdしてみましょう。
Set-Location : プロバイダがこの操作をサポートしていないため、プロバイダの実行が中止されました。 発生場所 行:1 文字:3 + cd <<<< hoge: