次の方法で共有


Windows PowerShellコンテナプロバイダーの作成

このトピックでは、多層データストアで動作する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*の実装には、以下の条件が適用される可能性があります:

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*の実装には、以下の条件が適用される可能性があります:

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*の実装には、以下の条件が適用される場合があります:

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*の実装には、以下の条件が適用される場合があります:

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*の実装には、以下の条件が適用される場合があります:

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.CopyItem メソッドを実装し、 Copy-Item コマンドレットからの呼び出しをサポートする必要があります。 この方法は、コマンドレットの path パラメータで示された位置から、データ項目を copyPath パラメータで示された位置にコピーします。 recurseパラメータが指定されている場合、メソッドはすべてのサブコンテナをコピーします。 パラメータが指定されていない場合、メソッドは単一のレベルのアイテムのみをコピーします。

このプロバイダーはこの手法を実装していません。 しかし、以下のコードは System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemのデフォルト実装です。

CopyItemの実装について覚えておくべきこと

System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemの実装には、以下の条件が適用される場合があります:

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データベースを使用していることに注意してください。

  1. 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       :
    
  2. Get-ChildItemコマンドレットを再度実行してテーブルのデータを取得します。

    (Get-ChildItem mydb:customers).Data
    

    以下の出力が掲載されます。

    TABLE_CAT   : C:\PS\northwind
    TABLE_SCHEM :
    TABLE_NAME  : Customers
    TABLE_TYPE  : TABLE
    REMARKS     :
    
  3. 次に 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     : 0
    
  4. Get-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
    
  5. 次に 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"
    
  6. 新しい項目操作の正しさは以下の通りに検証します。

    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
    

こちらもご覧ください

Windows PowerShell プロバイダーの作成

Windows PowerShellプロバイダーの設計

Implementing an Item Windows PowerShell Provider

ナビゲーション用Windows PowerShellプロバイダーの実装

コマンドレット、プロバイダー、ホストアプリケーションの登録方法

Windows PowerShell SDK

Windows PowerShell プログラマーズガイド