このトピックでは、多層データストアで動作するWindowsのPowerShellプロバイダーの作成方法について説明します。 この種のデータストアでは、ストアの最上位にルートアイテムが含まれ、各レベルは子項目のノードと呼ばれます。 ユーザーがこれらの子ノードに作業できるようにすることで、データはストアを通じて階層的にやり取りできます。
多層データストアで動作可能なプロバイダーはWindows PowerShellコンテナプロバイダーと呼ばれます。 ただし、Windows PowerShellコンテナプロバイダーは、1つのコンテナ(ネストコンテナなし)にアイテムが入っている場合にのみ使用できることに注意してください。 もしネストされたコンテナがある場合は、Windows PowerShellナビゲーションプロバイダーを実装する必要があります。 Windows PowerShellナビゲーションプロバイダーの実装についての詳細は、「 Windows PowerShellナビゲーションプロバイダーの作成」をご覧ください。
注
このプロバイダーのC#ソースファイル(AccessDBSampleProvider04.cs)は、Windows Vistaおよび.NET Framework 3.0ランタイムコンポーネント用のMicrosoft Windows Software Development Kitを使ってダウンロードできます。 ダウンロード手順については、「 Windows PowerShellのインストール方法」および「Windows PowerShell SDKのダウンロード」をご覧ください。 ダウンロードしたソースファイルは <PowerShell Samples> ディレクトリで利用可能です。 他のWindows PowerShellプロバイダー実装の詳細については、「 Windows PowerShell Providerの設計」をご覧ください。
ここで説明するWindowsのPowerShellコンテナプロバイダーは、データベースを単一のコンテナとして定義し、データベースのテーブルと行はコンテナの項目として定義されています。
注意事項
この設計は、名前IDを持つフィールドを持ち、そのフィールド型がLongIntegerであることを前提としています。
Windows PowerShell Container Provider Class の定義
Windows PowerShellコンテナプロバイダーは、 System.Management.Automation.Provider.ContainerCmdletProvider ベースクラスから派生する.NETクラスを定義しなければなりません。 こちらがこのセクションで説明されているWindows PowerShellコンテナプロバイダーのクラス定義です。
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : ContainerCmdletProvider
このクラス定義において、 System.Management.Automation.Provider.CmdletProviderAttribute 属性に2つのパラメータが含まれていることに注目してください。 最初のパラメータは、WindowsPowerShellで使用されるプロバイダーのユーザーフレンドリーな名前を指定します。 2つ目のパラメータは、コマンド処理中にプロバイダーがWindows PowerShellランタイムに公開するWindows PowerShell固有の能力を指定します。 このプロバイダーには、WindowsのPowerShell特有の機能が追加されていません。
基本機能の定義
「Designing Your Windows PowerShell Provider」で説明されているように、System.Management.Automation.Provider.ContainerCmdletProviderクラスは、異なるプロバイダー機能を提供する複数の他のクラスから派生しています。 したがって、WindowsのPowerShellコンテナプロバイダーは、これらのクラスが提供するすべての機能を定義する必要があります。
セッション固有の初期化情報の追加や、プロバイダで使用されるリソースの解放機能の実装については、「 Basic Windows PowerShell Providerの作成」を参照してください。 しかし、ほとんどのプロバイダー(ここで説明するプロバイダーを含む)は、Windows PowerShellが提供するこの機能のデフォルト実装を使用できます。
データストアにアクセスするためには、 プロバイダーはSystem.Management.Automation.Provider.DriveCmdletProvider のベースクラスのメソッドを実装しなければなりません。 これらのメソッドの実装についての詳細は、「 Windows PowerShell Drive Providerの作成」をご覧ください。
データストアの項目、例えば取得、設定、クリアなどを操作するには、 プロバイダーはSystem.Management.Automation.Provider.ItemCmdletProvider ベースクラスが提供するメソッドを実装しなければなりません。 これらのメソッドの実装についての詳細は、「 Windows PowerShell Item Providerの作成」をご覧ください。
子供アイテムの回収
子項目を取得するには、Windows PowerShellコンテナプロバイダーが System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドをオーバーライドし、 Get-ChildItem コマンドレットからの呼び出しをサポートしなければなりません。 このメソッドはデータストアから子アイテムを取得し、それらをオブジェクトとしてパイプラインに書き込みます。 コマンドレットの recurse パラメータが指定されている場合、メソッドはレベルに関係なくすべての子を取得します。
recurseパラメータが指定されていない場合、メソッドは子のレベルを1つだけ取得します。
こちらはこのプロバイダー向けの System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドの実装です。 このメソッドは、パスがAccessデータベースを示している場合、すべてのデータベーステーブルの子項目を取得し、パスがデータテーブルを示している場合はそのテーブルの行から子項目を取得します。
protected override void GetChildItems(string path, bool recurse)
{
// If path represented is a drive then the children in the path are
// tables. Hence all tables in the drive represented will have to be
// returned
if (PathIsDrive(path))
{
foreach (DatabaseTableInfo table in GetTables())
{
WriteItemObject(table, path, true);
// if the specified item exists and recurse has been set then
// all child items within it have to be obtained as well
if (ItemExists(path) && recurse)
{
GetChildItems(path + pathSeparator + table.Name, recurse);
}
} // foreach (DatabaseTableInfo...
} // if (PathIsDrive...
else
{
// Get the table name, row number and type of path from the
// path specified
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Table)
{
// Obtain all the rows within the table
foreach (DatabaseRowInfo row in GetRows(tableName))
{
WriteItemObject(row, path + pathSeparator + row.RowNumber,
false);
} // foreach (DatabaseRowInfo...
}
else if (type == PathType.Row)
{
// In this case the user has directly specified a row, hence
// just give that particular row
DatabaseRowInfo row = GetRow(tableName, rowNumber);
WriteItemObject(row, path + pathSeparator + row.RowNumber,
false);
}
else
{
// In this case, the path specified is not valid
ThrowTerminatingInvalidPathException(path);
}
} // else
} // GetChildItems
GetChildItemsの実装について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*の実装には、以下の条件が適用される可能性があります:
プロバイダークラスを定義する際、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.Provider.ProviderCapabilities の列挙からExpandWildcards、Filter、Include、またはExcludeのプロバイダー能力を宣言することがあります。 このような場合、 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドの実装は、そのメソッドに渡されるパスが指定された能力の要件を満たしていることを保証する必要があります。 これを行うには、メソッドは適切なプロパティにアクセスする必要があります。例えば 、System.Management.Automation.Provider.CmdletProvider.Exclude* や System.Management.Automation.Provider.CmdletProvider.Include* プロパティなどです。
このメソッドの実装には、ユーザーがアイテムを見える可能性のあるあらゆるアクセス形態を考慮しなければなりません。 例えば、ユーザーがファイルシステムプロバイダー(Windows PowerShell提供)を通じてファイルへの書き込みアクセス権を持ちながら読み取りアクセスがない場合、そのファイルは依然として存在し、 System.Management.Automation.Provider.ItemCmdletProvider.ItemExists* が
trueを返します。 実装では、子項目を列挙可能かどうかを確認する親項目のチェックが必要になるかもしれません。複数のアイテムを書く場合、 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドは時間がかかることがあります。 System.Management.Automation.Provider.CmdletProvider.WriteItemObject*メソッドを使って、アイテムを一つずつ書き込むようにプロバイダーを設計できます。 この手法を使うと、アイテムをストリームでユーザーに提示できます。
System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*の実装は、循環リンクなどの場合に無限再帰を防ぐ責任があります。 そのような条件を反映するために、適切な終了例外をスローする必要があります。
Get-ChildItem コマンドレットへの動的パラメータの付与
時には、System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*を呼び出すGet-ChildItemコマンドレットが、実行時に動的に指定される追加パラメータを必要とすることがあります。 これらの動的パラメータを提供するために、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItemsDynamicParameters* メソッドを実装する必要があります。 このメソッドは指定された経路のアイテムの動的パラメータを取得し、コマンドレットクラスや System.Management.Automation.RuntimeDefinedParameterDictionary オブジェクトに似た解析属性を持つプロパティやフィールドを持つオブジェクトを返します。 Windows PowerShellランタイムは、返されたオブジェクトを使ってパラメータを Get-ChildItem コマンドレットに追加します。
このWindows PowerShellコンテナプロバイダーはこのメソッドを実装していません。 しかし、以下のコードはこのメソッドのデフォルトの実装です。
子アイテム名の取得
子項目の名前を取得するためには、Windows PowerShellコンテナプロバイダがSystem.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames*メソッドをオーバーライドし、Nameパラメータが指定されたGet-ChildItemコマンドレットからの呼び出しをサポートします。 このメソッドは、コマンドレットの returnAllContainers パラメータが指定されている場合、指定されたパスの子項目名またはすべてのコンテナの子項目名を取得します。 子名はパスの葉部分です。 例えば、パス C:\windows\system32\abc.dll の子名は「abc.dll」です。 ディレクトリC:\windows\system32の子名は「system32」です。
こちらはこのプロバイダーに対する System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* メソッドの実装です。 指定されたパスがアクセスデータベース(ドライブ)を示している場合はテーブル名を取得し、パスがテーブルを示している場合は行番号を取得します。
protected override void GetChildNames(string path,
ReturnContainers returnContainers)
{
// If the path represented is a drive, then the child items are
// tables. get the names of all the tables in the drive.
if (PathIsDrive(path))
{
foreach (DatabaseTableInfo table in GetTables())
{
WriteItemObject(table.Name, path, true);
} // foreach (DatabaseTableInfo...
} // if (PathIsDrive...
else
{
// Get type, table name and row number from path specified
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Table)
{
// Get all the rows in the table and then write out the
// row numbers.
foreach (DatabaseRowInfo row in GetRows(tableName))
{
WriteItemObject(row.RowNumber, path, false);
} // foreach (DatabaseRowInfo...
}
else if (type == PathType.Row)
{
// In this case the user has directly specified a row, hence
// just give that particular row
DatabaseRowInfo row = GetRow(tableName, rowNumber);
WriteItemObject(row.RowNumber, path, false);
}
else
{
ThrowTerminatingInvalidPathException(path);
}
} // else
} // GetChildNames
GetChildNamesの実装について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*の実装には、以下の条件が適用される可能性があります:
プロバイダークラスを定義する際、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.Provider.ProviderCapabilities の列挙からExpandWildcards、Filter、Include、またはExcludeのプロバイダー能力を宣言することがあります。 このような場合、 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドの実装は、そのメソッドに渡されるパスが指定された能力の要件を満たしていることを保証する必要があります。 これを行うには、メソッドは適切なプロパティにアクセスする必要があります。例えば 、System.Management.Automation.Provider.CmdletProvider.Exclude* や System.Management.Automation.Provider.CmdletProvider.Include* プロパティなどです。
注
ただし、コマンドレットの
returnAllContainersパラメータが指定されている場合に例外が生じます。 この場合、メソッドは System.Management.Automation.Provider.CmdletProvider.Filter*、 System.Management.Automation.Provider.CmdletProvider.Include*、または System.Management.Automation.Provider.CmdletProvider.Exclude* プロパティの値と一致しなくても、コンテナの子名を取得すべきです。デフォルトでは、このメソッドのオーバーライドは、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティが指定されていない限り、ユーザーに隠されているオブジェクト名を取得することはありません。 指定されたパスがコンテナを示している場合、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティは必要ありません。
System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames*の実装は、循環リンクなどの場合に無限再帰を防ぐ責任があります。 そのような条件を反映するために、適切な終了例外をスローする必要があります。
Get-ChildItem コマンドレット(名前)に動的パラメータを付ける方法
時には Get-ChildItem コマンドレット( Name パラメータ付き)が実行時に動的に指定される追加パラメータを必要とすることがあります。 これらの動的パラメータを提供するために、Windows PowerShellコンテナプロバイダは System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNamesDynamicParameters* メソッドを実装しなければなりません。 このメソッドは指定されたパス上のアイテムの動的パラメータを取得し、コマンドレットクラスや System.Management.Automation.RuntimeDefinedParameterDictionary オブジェクトに似た解析属性を持つプロパティとフィールドを持つオブジェクトを返します。 Windows PowerShellランタイムは、返されたオブジェクトを使ってパラメータを Get-ChildItem コマンドレットに追加します。
このプロバイダーはこの手法を実装していません。 しかし、以下のコードはこのメソッドのデフォルトの実装です。
項目の名称変更
アイテム名を変更するには、Windows PowerShellコンテナプロバイダーが System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* メソッドをオーバーライドし、 Rename-Item コマンドレットからの呼び出しをサポートする必要があります。 このメソッドは指定された経路のアイテム名を新たに変更します。 新しい名前は常に親項目(コンテナ)に対して相対的でなければなりません。
このプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* メソッドを上書きしません。 しかし、以下がデフォルトの実装です。
RenameItemの実装について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem*の実装には、以下の条件が適用される場合があります:
プロバイダークラスを定義する際、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.Provider.ProviderCapabilities の列挙からExpandWildcards、Filter、Include、またはExcludeのプロバイダー能力を宣言することがあります。 このような場合、 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドの実装は、そのメソッドに渡されるパスが指定された能力の要件を満たしていることを保証する必要があります。 これを行うには、メソッドは適切なプロパティにアクセスする必要があります。例えば 、System.Management.Automation.Provider.CmdletProvider.Exclude* や System.Management.Automation.Provider.CmdletProvider.Include* プロパティなどです。
System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* メソッドは、アイテム名の変更のみを目的としており、移動操作には使いません。 メソッドの実装は、
newNameパラメータにパスセパレーターが含まれている場合、または親の位置が変わる原因となるエラーを書くはずです。デフォルトでは、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティが指定されていない限り、このメソッドのオーバーライドはオブジェクト名を変更しません。 指定されたパスがコンテナを示している場合、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティは必要ありません。
System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem*メソッドの実装は、データストアに変更を加える前にSystem.Management.Automation.Provider.CmdletProvider.ShouldProcessを呼び出し、返却値を確認するべきです。 この方法は、システム状態に変更があった場合、例えばファイル名の変更など、操作の実行を確認するために使用されます。 System.Management.Automation.Provider.CmdletProvider.ShouldProcess は、変更するリソース名をユーザーに送信し、Windows PowerShellランタイムはコマンドラインの設定や好み変数を考慮して表示すべき内容を決定します。
System.Management.Automation.Provider.CmdletProvider.ShouldProcessへの呼び出しが
true返された後、System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem*メソッドはSystem.Management.Automation.Provider.CmdletProvider.CommandletProvider.ShouldContinueメソッドを呼び出すべきです。 この方法は、操作を継続すべきかどうかを判断するための追加のフィードバックを得るために、ユーザーに確認メッセージを送信します。 プロバイダーは、潜在的に危険なシステム変更の追加チェックとして System.Management.Automation.Provider.CmdletProvider.WithWithContinue に連絡してください。
Rename-Item コマンドレットへの動的パラメータの付与
時には Rename-Item コマンドレットが実行時に動的に指定される追加パラメータを必要とすることもあります。 これらの動的パラメータを提供するために、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.RenameItemDynamicParameters* メソッドを実装しなければなりません。 このメソッドは指定されたパス上のアイテムのパラメータを取得し、コマンドレットクラスや System.Management.Automation.RuntimeDefinedParameterDictionary オブジェクトに似た解析属性を持つプロパティとフィールドを持つオブジェクトを返します。 Windows PowerShellランタイムは、返されたオブジェクトを使ってパラメータを Rename-Item コマンドレットに追加します。
このコンテナプロバイダーはこの手法を実装していません。 しかし、以下のコードはこのメソッドのデフォルトの実装です。
新しいアイテムの作成
新しい項目を作成するには、コンテナプロバイダーがNew-Itemコマンドレットからの呼び出しをサポートするためにSystem.Management.Automation.Provider.ContainerCmdletProvider.NewItem*メソッドを実装する必要があります。 このメソッドは指定されたパス上にデータ項目を作成します。 コマンドレットの type パラメータは新しいアイテムのプロバイダー定義型を含みます。 例えば、ファイルシステムプロバイダーは「ファイル」または「ディレクトリ」という値の type パラメータを使用します。 コマンドレットの newItemValue パラメータは、新しいアイテムに対してプロバイダー固有の値を指定します。
こちらはこのプロバイダーに対する System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* メソッドの実装です。
protected override void NewItem( string path, string type, object newItemValue )
{
// Create the new item here after
// performing necessary validations
//
// WriteItemObject(newItemValue, path, false);
// Example
//
// if (ShouldProcess(path, "new item"))
// {
// // Create a new item and then call WriteObject
// WriteObject(newItemValue, path, false);
// }
} // NewItem
{
case 1:
{
string name = pathChunks[0];
if (TableNameIsValid(name))
{
tableName = name;
retVal = PathType.Table;
}
}
break;
case 2:
{
string name = pathChunks[0];
NewItemの導入について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*の実装には、以下の条件が適用される場合があります:
System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*メソッドは、
typeパラメータで渡された文字列の大文字を区別しない比較を行うはずです。 また、曖昧さの少ないマッチングも可能になるはずです。 例えば、「file」や「directory」という型では、曖昧さを解消するために最初の文字だけで十分です。typeパラメータがプロバイダーが作成できないタイプを示している場合、System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*メソッドは、プロバイダーが作成可能なタイプを示すメッセージ付きのArgumentExceptionを書き込むはずです。newItemValueパラメータについては、System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*メソッドの実装で、最低限文字列を受け入れることが推奨されています。 また、 System.Management.Automation.Provider.ItemCmdletProvider.GetItem* メソッドで取得されるオブジェクトの種類も同じパスで受け入れられるはずです。 System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* メソッドは、System.Management.Automation.LanguagePrimitives.ConvertTo* メソッドを使って型を目的の型に変換できます。System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*メソッドの実装は、System.Management.Automation.Provider.CmdletProvider.ShouldProcessを呼び出して、データストアに変更を加える前に返却値を確認すべきです。 System.Management.Automation.Provider.CmdletProvider.ShouldProcessへの呼び出しがtrueに戻った後、System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*メソッドは、潜在的に危険なシステム変更の追加チェックとしてSystem.Management.Automation.Provider.CmdletProvider.ShouldContinueメソッドを呼び出すべきです。
New-Item コマンドレットへの動的パラメータの付与
時には New-Item コマンドレットが実行時に動的に指定される追加パラメータを必要とすることもあります。 これらの動的パラメータを提供するためには、コンテナプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.NewItemDynamicParameters* メソッドを実装しなければなりません。 このメソッドは指定されたパス上のアイテムのパラメータを取得し、コマンドレットクラスや System.Management.Automation.RuntimeDefinedParameterDictionary オブジェクトに似た解析属性を持つプロパティとフィールドを持つオブジェクトを返します。 Windows PowerShellランタイムは、返されたオブジェクトを使ってパラメータを New-Item コマンドレットに追加します。
このプロバイダーはこの手法を実装していません。 しかし、以下のコードはこのメソッドのデフォルトの実装です。
アイテムの削除
アイテムを削除するには、WindowsのPowerShellプロバイダーが System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem* メソッドをオーバーライドし、 Remove-Item コマンドレットからの呼び出しをサポートしなければなりません。 このメソッドは指定されたパスでデータストアからアイテムを削除します。
Remove-Itemコマンドレットのrecurseパラメータがtrueに設定されている場合、メソッドはレベルに関係なくすべての子項目を削除します。 パラメータが falseに設定されている場合、メソッドは指定されたパスで1つのアイテムのみを取り除きます。
このプロバイダーはアイテムの削除をサポートしていません。 しかし、以下のコードは System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*のデフォルト実装です。
RemoveItemの実装について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*の実装には、以下の条件が適用される場合があります:
プロバイダークラスを定義する際、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.Provider.ProviderCapabilities の列挙からExpandWildcards、Filter、Include、またはExcludeのプロバイダー能力を宣言することがあります。 このような場合、 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドの実装は、そのメソッドに渡されるパスが指定された能力の要件を満たしていることを保証する必要があります。 これを行うには、メソッドは適切なプロパティにアクセスする必要があります。例えば 、System.Management.Automation.Provider.CmdletProvider.Exclude* や System.Management.Automation.Provider.CmdletProvider.Include* プロパティなどです。
デフォルトでは、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティがtrueに設定されていない限り、このメソッドのオーバーライドはオブジェクトを削除しません。 指定されたパスがコンテナを示している場合、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティは必要ありません。
System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*の実装は、循環リンクなどの場合に無限再帰を防ぐ責任があります。 そのような条件を反映するために、適切な終了例外をスローする必要があります。
System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*メソッドの実装は、データストアに変更を加える前にSystem.Management.Automation.Provider.CmdletProvider.ShouldProcessを呼び出し、返還値を確認するべきです。 System.Management.Automation.Provider.CmdletProvider.ShouldProcessへの呼び出しが
true返された後、System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*メソッドは、潜在的に危険なシステム変更の追加チェックとしてSystem.Management.Automation.Provider.CmdletProvider.ShouldContinueメソッドを呼び出すべきです。
Remove-Item コマンドレットへの動的パラメータの付与
時には Remove-Item コマンドレットが実行時に動的に指定される追加パラメータを必要とすることもあります。 これらの動的パラメータを提供するために、コンテナプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters* メソッドを実装し、これらのパラメータを処理する必要があります。 このメソッドは指定されたパス上のアイテムの動的パラメータを取得し、コマンドレットクラスや System.Management.Automation.RuntimeDefinedParameterDictionary オブジェクトに似た解析属性を持つプロパティとフィールドを持つオブジェクトを返します。 Windows PowerShellランタイムは、返されたオブジェクトを使ってパラメータを Remove-Item コマンドレットに追加します。
このコンテナプロバイダーはこの手法を実装していません。 しかし、以下のコードは System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters*のデフォルト実装です。
子項目のクエリ
指定されたパスに子項目が存在するかどうかを確認するために、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* メソッドをオーバーライドする必要があります。 このメソッドは、アイテムに子がある場合は true を返し、そうでなければ返 false します。 nullまたは空のパスの場合、メソッドはデータストア内の任意の項目を子とみなし、 true返します。
こちらが System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* メソッドのオーバーライドです。 ChunkPathヘルパーメソッドで作成されるパスパートが2つ以上ある場合、データベースコンテナとテーブルコンテナのみが定義されているため、メソッドは falseを返します。 このヘルパーメソッドの詳細については、「 Creating a Windows PowerShell Item Provider」で説明されているChunkPathメソッドを参照してください。
protected override bool HasChildItems( string path )
{
return false;
} // HasChildItems
ErrorCategory.InvalidOperation, tableName));
}
return results;
HasChildItemsの実装について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems*の実装には、以下の条件が適用される場合があります:
- コンテナプロバイダーが興味深いマウントポイントを含むルートを公開した場合、 System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* メソッドの実装は、パスに対してnullや空文字列が渡されたときに
true返すはずです。
アイテムのコピー
アイテムをコピーするには、コンテナプロバイダーが System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem メソッドを実装し、 Copy-Item コマンドレットからの呼び出しをサポートする必要があります。 この方法は、コマンドレットの path パラメータで示された位置から、データ項目を copyPath パラメータで示された位置にコピーします。
recurseパラメータが指定されている場合、メソッドはすべてのサブコンテナをコピーします。 パラメータが指定されていない場合、メソッドは単一のレベルのアイテムのみをコピーします。
このプロバイダーはこの手法を実装していません。 しかし、以下のコードは System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemのデフォルト実装です。
CopyItemの実装について覚えておくべきこと
System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemの実装には、以下の条件が適用される場合があります:
プロバイダークラスを定義する際、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.Provider.ProviderCapabilities の列挙からExpandWildcards、Filter、Include、またはExcludeのプロバイダー能力を宣言することがあります。 このような場合、 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* メソッドの実装は、そのメソッドに渡されるパスが指定された能力の要件を満たしていることを保証する必要があります。 これを行うには、メソッドは適切なプロパティにアクセスする必要があります。例えば 、System.Management.Automation.Provider.CmdletProvider.Exclude* や System.Management.Automation.Provider.CmdletProvider.Include* プロパティなどです。
デフォルトでは、 System.Management.Automation.Provider.CmdletProvider.Force* プロパティが
trueに設定されていない限り、このメソッドのオーバーライドは既存オブジェクトにオブジェクトをコピーしません。 例えば、 FileSystemプロバイダーはSystem.Management.Automation.Provider.CmdletProvider.Force* プロパティがtrueに設定されていない限り、既存の C:\abc.txt ファイルに C:\temp\abc.txt をコピーしません。copyPathパラメータで指定されたパスが存在し、コンテナを示す場合、System.Management.Automation.Provider.CmdletProvider.Force*プロパティは必須ではありません。 この場合、 System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem は、pathパラメータで示されたアイテムをcopyPathパラメータで示されたコンテナに子としてコピーすべきです。System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemの実装は、循環リンクなどの場合に無限再帰を防ぐ責任があります。 そのような条件を反映するために、適切な終了例外をスローする必要があります。
System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemメソッドの実装は、System.Management.Automation.Provider.CmdletProvider.ShouldProcessを呼び出して、データストアに変更を加える前に返り値を確認するべきです。 System.Management.Automation.Provider.CmdletProvider.ShouldProcessへの呼び出しがtrueに戻った後、System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemメソッドは、潜在的に危険なシステム変更の追加チェックとしてSystem.Management.Automation.Provider.CmdletProvider.ShouldContinueメソッドを呼び出すべきです。 これらのメソッドを呼び出す方法の詳細については、「 Rename Items」をご覧ください。
Copy-Item コマンドレットへの動的パラメータの付与
時には Copy-Item コマンドレットが実行時に動的に指定される追加パラメータを必要とすることもあります。 これらの動的パラメータを提供するために、Windows PowerShellコンテナプロバイダーは System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters* メソッドを実装し、これらのパラメータを処理する必要があります。 このメソッドは指定されたパス上のアイテムのパラメータを取得し、コマンドレットクラスや System.Management.Automation.RuntimeDefinedParameterDictionary オブジェクトに似た解析属性を持つプロパティとフィールドを持つオブジェクトを返します。 Windows PowerShellランタイムは、返されたオブジェクトを使ってパラメータを Copy-Item コマンドレットに追加します。
このプロバイダーはこの手法を実装していません。 しかし、以下のコードは System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters*のデフォルト実装です。
コード サンプル
完全なサンプルコードについては、 AccessDbProviderSample04 Code Sampleをご覧ください。
Windows PowerShell プロバイダーの構築
「 コマンドレット、プロバイダー、ホスティングアプリケーションの登録方法」を参照してください。
Windows PowerShellプロバイダーのテスト
Windows PowerShellプロバイダーがWindows PowerShellに登録されたら、コマンドラインでサポートされているコマンドレットを実行してテストできます。 以下の例は架空のAccessデータベースを使用していることに注意してください。
Get-ChildItemコマンドレットを実行して、AccessデータベースのCustomersテーブルから子項目のリストを取得します。Get-ChildItem mydb:customers以下の出力が掲載されます。
PSPath : AccessDB::customers PSDrive : mydb PSProvider : System.Management.Automation.ProviderInfo PSIsContainer : True Data : System.Data.DataRow Name : Customers RowCount : 91 Columns :Get-ChildItemコマンドレットを再度実行してテーブルのデータを取得します。(Get-ChildItem mydb:customers).Data以下の出力が掲載されます。
TABLE_CAT : C:\PS\northwind TABLE_SCHEM : TABLE_NAME : Customers TABLE_TYPE : TABLE REMARKS :次に
Get-Itemコマンドレットを使ってデータテーブルの0行目のアイテムを取得します。Get-Item mydb:\customers\0以下の出力が掲載されます。
PSPath : AccessDB::customers\0 PSDrive : mydb PSProvider : System.Management.Automation.ProviderInfo PSIsContainer : False Data : System.Data.DataRow RowNumber : 0Get-Itemを再利用して、行0の項目のデータを取得します。(Get-Item mydb:\customers\0).Data以下の出力が掲載されます。
CustomerID : 1234 CompanyName : Fabrikam ContactName : Eric Gruber ContactTitle : President Address : 4567 Main Street City : Buffalo Region : NY PostalCode : 98052 Country : USA Phone : (425) 555-0100 Fax : (425) 555-0101次に
New-Itemコマンドレットを使って既存のテーブルに行を追加します。Pathパラメータは行までの完全な経路を指定し、テーブル内の既存の行数よりも多い行数を示す必要があります。Typeパラメータは、追加するアイテムの種類を指定するRowを示します。 最後に、Valueパラメータは行のカラム値のカンマ区切られたリストを指定します。New-Item -Path mydb:\Customers\3 -ItemType "Row" -Value "3,CustomerFirstName,CustomerLastName,CustomerEmailAddress,CustomerTitle,CustomerCompany,CustomerPhone, CustomerAddress,CustomerCity,CustomerState,CustomerZip,CustomerCountry"新しい項目操作の正しさは以下の通りに検証します。
PS mydb:\> cd Customers PS mydb:\Customers> (Get-Item 3).Data以下の出力が掲載されます。
ID : 3 FirstName : Eric LastName : Gruber Email : ericgruber@fabrikam.com Title : President Company : Fabrikam WorkPhone : (425) 555-0100 Address : 4567 Main Street City : Buffalo State : NY Zip : 98052 Country : USA
こちらもご覧ください
Implementing an Item Windows PowerShell Provider
ナビゲーション用Windows PowerShellプロバイダーの実装