共用方式為


建立 Windows PowerShell 容器提供者

本主題說明如何建立一個能在多層資料儲存上運作的 Windows PowerShell 提供者。 對於這種類型的資料儲存,儲存的頂層包含根項目,每個後續層級稱為子節點。 透過允許使用者在這些子節點上工作,使用者可以透過資料儲存庫進行階層式互動。

能在多層資料儲存上運作的提供者稱為 Windows PowerShell 容器提供者。 不過請注意,Windows PowerShell 容器提供者只能在有一個容器(無巢狀容器)且包含項目時使用。 如果有巢狀容器,那你必須實作 Windows PowerShell 導覽提供者。 欲了解更多關於實作 Windows PowerShell 導覽服務的資訊,請參閱 建立 Windows PowerShell 導覽服務提供者

備註

你可以使用 Windows Vista 和 .NET Framework 3.0 執行元件的 Microsoft Windows 軟體開發套件下載 C# 原始碼檔案(AccessDBSampleProvider04.cs)。 如需下載說明,請參閱 《如何安裝 Windows PowerShell》及《Download the Windows PowerShell SDK》。 下載的原始碼檔案可在 <PowerShell 範例> 目錄中取得。 欲了解更多關於其他 Windows PowerShell 提供者實作的資訊,請參閱 「設計您的 Windows PowerShell 提供者」。

此處描述的 Windows PowerShell 容器提供者定義資料庫為其單一容器,資料庫的表格與列定義為容器中的項目。

謹慎

請注意,此設計假設資料庫中有一個名為 ID 的欄位,且欄位類型為 LongInteger。

定義 Windows PowerShell 容器提供者類別

Windows PowerShell 容器提供者必須定義一個 .NET 類別,該類別源自 System.Management.Automation.Provider.ContainerCmdletProvider 基底類別。 以下是本節所述 Windows PowerShell 容器提供者的類別定義。

[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : ContainerCmdletProvider

請注意,在這個類別定義中, System.Management.Automation.Provider.CmdletProviderAttribute 屬性包含兩個參數。 第一個參數指定了 Windows PowerShell 所使用的使用者友善提供者名稱。 第二個參數指定了 Windows PowerShell 在指令處理過程中,向 Windows PowerShell 執行時所暴露的能力。 對於這個提供者,並沒有新增任何 Windows PowerShell 專屬的功能。

定義基礎功能

如《 設計您的 Windows PowerShell 提供者》所述, System.Management.Automation.Provider.ContainerCmdletProvider 類別源自多個提供不同提供者功能的類別。 因此,Windows PowerShell 容器提供者需要定義這些類別所提供的所有功能。

若要實作新增會話特定初始化資訊及釋放提供者使用的資源的功能,請參見 建立基本 Windows PowerShell 提供者。 然而,大多數提供者(包括此處描述的提供者)都能使用 Windows PowerShell 提供的預設實作。

要取得資料儲存庫的存取權,提供者必須實作 System.Management.Automation.Provider.DriveCmdletProvider 基底類別的方法。 欲了解更多實作這些方法的資訊,請參閱 建立 Windows PowerShell 磁碟機提供者

為了操作資料庫中的項目,例如取得、設定和清除項目,提供者必須實作 System.Management.Automation.Provider.ItemCmdletProvider 基底類別所提供的方法。 欲了解更多實作這些方法的資訊,請參閱 建立 Windows PowerShell 項目提供者

取回兒童物品

要取得子項目,Windows PowerShell 容器提供者必須覆寫 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* 方法,以支援該 Get-ChildItem 指令的呼叫。 此方法從資料儲存庫取得子項目,並將其寫入管線作為物件。 如果 recurse 指定 cmdlet 的參數,該方法會擷取所有子節點,不論它們處於何層級。 若未指定參數 recurse ,該方法只會取得單一層級的子節點。

以下是 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 cmdlet 需要在執行時動態指定額外參數。 為了提供這些動態參數,Windows PowerShell 容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItemsDynamicParameters* 方法。 此方法會取得指定路徑項目的動態參數,並回傳一個具有類似 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件的屬性與欄位的物件。 Windows PowerShell 執行時會使用回傳的物件來將參數加入 Get-ChildItem cmdlet。

這個 Windows PowerShell 容器提供者並未實作此方法。 然而,以下程式碼是此方法的預設實作。

取回子項目名稱

為了取得子項目的名稱,Windows PowerShell 容器提供者必須覆寫 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* 方法,以支援在Name指定參數時從Get-ChildItem該指令元呼叫。 此方法會取得指定路徑的子項目名稱,或若 returnAllContainers cmdlet 參數指定,則取得所有容器的子項目名稱。 子名稱是路徑中葉子部分。 例如,路徑 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 cmdlet(包含參數 Name )需要額外參數,這些參數會在執行時動態指定。 為了提供這些動態參數,Windows PowerShell 容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNamesDynamicParameters* 方法。 此方法會取得指定路徑項目的動態參數,並回傳一個具有屬性與欄位的物件,解析屬性類似於 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件。 Windows PowerShell 執行時會使用回傳的物件來將參數加入 Get-ChildItem cmdlet。

該提供者並未實作此方法。 然而,以下程式碼是此方法的預設實作。

項目更名

要重新命名項目,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 cmdlet 需要額外參數,這些參數會在執行時動態指定。 為了提供這些動態參數,Windows PowerShell 容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.RenameItemDynamicParameters* 方法。 此方法取得指定路徑上的項目參數,並回傳一個具有屬性與欄位的物件,解析屬性類似 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件。 Windows PowerShell 執行時會使用回傳的物件來將參數加入 Rename-Item cmdlet。

此容器提供者未實作此方法。 然而,以下程式碼是此方法的預設實作。

創建新物品

要建立新項目,容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* 方法來支援 cmdlet 的呼叫 New-Item 。 此方法會建立位於指定路徑的資料項目。 type cmdlet 的參數包含新項目的提供者定義型別。 例如,檔案系統提供者使用 type 一個參數,值為「file」或「directory」。 newItemValue cmdlet 的參數指定新項目的提供者專屬值。

以下是 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 cmdlet 需要額外參數,這些參數會在執行時動態指定。 為了提供這些動態參數,容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.NewItemDynamicParameters* 方法。 此方法取得指定路徑上的項目參數,並回傳一個具有屬性與欄位的物件,解析屬性類似 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件。 Windows PowerShell 執行時會使用回傳的物件來將參數加入 New-Item cmdlet。

該提供者並未實作此方法。 然而,以下程式碼是此方法的預設實作。

移除物品

要移除項目,Windows PowerShell 提供者必須覆寫 System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem* 方法,以支援從 cmdlet 呼叫 Remove-Item 。 此方法會在指定路徑上從資料儲存中刪除一個項目。 若 recurseRemove-Item cmdlet 參數設為 true,該方法會移除所有子項目,不論其等級如何。 若參數設為 false,該方法僅移除指定路徑上的單一項目。

此服務提供者不支援物品移除。 然而,以下程式碼是 System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem* 的預設實作。

關於實作 RemoveItem 需要注意的事項

以下條件可能適用於您對 System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* 的實作:

將動態參數附加於 Remove-Item 指令小子

有時 Remove-Item cmdlet 需要額外參數,這些參數會在執行時動態指定。 為了提供這些動態參數,容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters* 方法來處理這些參數。 此方法會取得指定路徑項目的動態參數,並回傳一個具有屬性與欄位的物件,解析屬性類似於 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件。 Windows PowerShell 執行時會使用回傳的物件來將參數加入 Remove-Item cmdlet。

此容器提供者未實作此方法。 然而,以下程式碼是 System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters* 的預設實作。

查詢子項目

為了檢查指定路徑是否存在子項目,Windows PowerShell 容器提供者必須覆寫 System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* 方法。 若該項目有子節點false,則此方法會回傳,否則則回傳true。 對於空路徑或空路徑,方法將資料儲存中的任意項目視為子節點,並回傳 true

這是 System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* 方法的覆寫。 如果 ChunkPath 輔助方法產生超過兩個路徑部分,該方法會回傳 false,因為只定義了資料庫容器和資料表容器。 欲了解更多關於此輔助方法的資訊,請參閱「 建立 Windows PowerShell 項目提供者」中討論的 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 cmdlet 需要額外參數,這些參數會在執行時動態指定。 為了提供這些動態參數,Windows PowerShell 容器提供者必須實作 System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters* 方法來處理這些參數。 此方法取得指定路徑上的項目參數,並回傳一個具有屬性與欄位的物件,解析屬性類似 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件。 Windows PowerShell 執行時會使用回傳的物件來將參數加入 Copy-Item cmdlet。

該提供者並未實作此方法。 然而,以下程式碼是 System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters* 的預設實作。

程式碼範例

完整範例程式碼請參見 AccessDbProviderSample04 程式碼範例

建置 Windows PowerShell 提供者

請參閱 如何註冊指令長、提供者及主機應用程式

測試 Windows PowerShell 提供者

當你的 Windows PowerShell 提供者已經註冊到 Windows PowerShell 後,你可以在命令列執行支援的 cmdlets 來測試。 請注意,以下範例輸出使用了一個虛構的 Access 資料庫。

  1. 執行 Get-ChildItem cmdlet 從 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 cmdlet 以取得資料表的資料。

    (Get-ChildItem mydb:customers).Data
    

    以下輸出結果顯示。

    TABLE_CAT   : C:\PS\northwind
    TABLE_SCHEM :
    TABLE_NAME  : Customers
    TABLE_TYPE  : TABLE
    REMARKS     :
    
  3. 現在用 Get-Item cmdlet 在資料表第 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 cmdlet 把一列加入現有的資料表。 參數 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 提供者

如何註冊 cmdlet、提供者及主機應用程式

Windows PowerShell SDK

Windows PowerShell 程式設計師指南