本主題說明如何建立一個 Windows PowerShell 導覽提供者,以導航資料儲存庫。 這類提供者支援遞迴指令、巢狀容器和相對路徑。
備註
你可以使用 Windows Vista 和 .NET Framework 3.0 執行時元件的 Microsoft Windows 軟體開發套件下載 C# 原始碼檔案(AccessDBSampleProvider05.cs)。 如需下載說明,請參閱 《如何安裝 Windows PowerShell》及《Download the Windows PowerShell SDK》。 下載的原始碼檔案可在 <PowerShell 範例> 目錄中取得。 欲了解更多關於其他 Windows PowerShell 提供者實作的資訊,請參閱 「設計您的 Windows PowerShell 提供者」。
此處描述的提供者允許使用者將 Access 資料庫視為磁碟機,讓使用者能導航至資料庫中的資料表。 在建立自己的導航提供者時,你可以實作一些方法,使得導航必須有 drive-qualified 路徑、正規化相對路徑、移動資料庫中的項目,以及取得子名稱、取得項目的父路徑,並測試項目是否為容器的方法。
謹慎
請注意,此設計假設資料庫中有一個名為 ID 的欄位,且欄位類型為 LongInteger。
定義 Windows PowerShell 提供者
Windows PowerShell 導航提供者必須建立一個 .NET 類別,該類別源自 System.Management.Automation.Provider.NavigationCmdletProvider 基底類別。 以下是本節所述的導航提供者類別定義。
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : NavigationCmdletProvider
請注意,在此提供者中, System.Management.Automation.Provider.CmdletProviderAttribute 屬性包含兩個參數。 第一個參數指定了 Windows PowerShell 所使用的使用者友善提供者名稱。 第二個參數指定了 Windows PowerShell 在指令處理過程中,向 Windows PowerShell 執行時所暴露的能力。 對於這個提供者,並沒有新增任何 Windows PowerShell 專屬的功能。
定義基礎功能
如 Design Your PS Provider 所述, System.Management.Automation.Provider.NavigationCmdletProvider 基底類別源自多個提供不同提供者功能的類別。 因此,Windows PowerShell 導覽提供者必須定義這些類別所提供的所有功能。
若要實作新增會話特定初始化資訊及釋放提供者使用的資源的功能,請參見 建立基本 PS 提供者。 然而,大多數提供者(包括此處描述的提供者)都能使用 Windows PowerShell 預設的此功能實作。
若要透過 Windows PowerShell 磁碟機存取資料儲存庫,您必須實作 System.Management.Automation.Provider.DriveCmdletProvider 基底類別的方法。 欲了解更多實作這些方法的資訊,請參閱 建立 Windows PowerShell 磁碟機提供者。
為了操作資料庫中的項目,例如取得、設定和清除項目,提供者必須實作 System.Management.Automation.Provider.ItemCmdletProvider 基底類別所提供的方法。 欲了解更多實作這些方法的資訊,請參閱 建立 Windows PowerShell 項目提供者。
要存取資料儲存的子項目或其名稱,以及建立、複製、重新命名和移除項目的方法,你必須實作 System.Management.Automation.Provider.ContainerCmdletProvider 基底類別所提供的方法。 欲了解更多實作這些方法的資訊,請參閱 建立 Windows PowerShell 容器提供者。
建立 Windows PowerShell 路徑
Windows PowerShell 導航提供者使用 provider-internal 的 Windows PowerShell 路徑來導航資料儲存中的項目。 要建立提供者內部路徑,提供者必須實作 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法,以支援 Combine-Path 指令元的呼叫。 此方法將父路徑與子路徑合併為提供者-內部路徑,並使用提供者專用的路徑分隔符來連接父子路徑。
預設實作會將路徑分隔符為「/」或「\」,將路徑分隔符正規化為「\」,將父路徑與子路徑部分與分隔符合併,然後回傳包含合併路徑的字串。
此導航提供者未實作此方法。 然而,以下程式碼是 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法的預設實作。
實作 MakePath 需要注意的事項
以下條件可能適用於您對 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 的實作:
你實作的 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法,不應在提供者命名空間中驗證該路徑是否合法且完全合格。 請注意,每個參數只能代表路徑的一部分,而合併後的部分可能無法產生完全限定的路徑。 例如, System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法中,檔案系統提供者可能會在參數中接收「windows\system32」
parent,參數中child為「abc.dll」。 該方法會將這些值與「\」分隔符連接,並回傳「windows\system32\abc.dll」,這並非完全限定的檔案系統路徑。這很重要
在呼叫 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 時所提供的路徑部分,可能包含提供者命名空間中不允許的字元。 這些字元很可能用於萬用牌擴充,且此方法的實作不應移除它們。
取回父路徑
Windows PowerShell 的導航提供者實作了 System.Management.Automation.Provider.NavigationCmdletProvider.GetParentPath* 方法,以取得指定完整或部分提供者特定路徑的父部分。 此方法會移除路徑的子部分,並回傳父路徑部分。 參數 root 指定了指向硬碟根節點的完全限定路徑。 若未使用已掛載硬碟進行擷取操作,此參數可為空或為空。 若指定根節點,該方法必須回傳與根節點同一樹中容器的路徑。
範例導航提供者不會覆寫此方法,而是使用預設實作。 它接受同時使用「/」和「\」作為路徑分隔符的路徑。 它首先將路徑正規化為僅有「\」分隔符,然後在最後一個「\」處將父路徑分出,並回傳父路徑。
要記得實作 GetParentPath 的事
你實作的 System.Management.Automation.Provider.NavigationCmdletProvider.GetParentPath* 方法,應該會在提供者命名空間的路徑分隔符上,以詞彙方式分割路徑。 例如,FileSystem 提供者會使用此方法尋找最後一個「\」,並回傳分隔符左側的所有資料。
取回子路徑名稱
您的導航提供者實作 System.Management.Automation.Provider.NavigationCmdletProvider.GetChildName* 方法,以取得位於指定完整或部分提供者特定路徑的項目子節點名稱(葉節點元素)。
範例導航提供者不會覆寫此方法。 預設實作如下所示。 它接受同時使用「/」和「\」作為路徑分隔符的路徑。 它首先將路徑正規化為僅有「\」分隔符,然後在最後一個「\」處將父路徑分離,並回傳子路徑部分的名稱。
實作 GetChildName 時需要注意的事項
你實作的 System.Management.Automation.Provider.NavigationCmdletProvider.GetChildName* 方法應該會在路徑分隔符上以詞彙方式分割路徑。 若所提供的路徑不包含路徑分隔符,該方法應回傳未修改的路徑。
這很重要
呼叫此方法時所提供的路徑可能包含在提供者命名空間中非法的字元。 這些字元很可能用於萬用字展開或正則表達式匹配,且此方法的實作不應移除它們。
判斷物品是否為容器
導航提供者可以實作 System.Management.Automation.Provider.NavigationCmdletProvider.IsItemContainer* 方法,以判斷指定的路徑是否代表容器。 如果路徑代表容器,則回傳 true;否則為 false。 使用者需要此方法才能使用 Test-Path 指令碼來執行所提供路徑。
以下程式碼展示了我們範例導航提供者中 System.Management.Automation.Provider.NavigationCmdletProvider.IsItemContainer* 的實作。 該方法會驗證指定的路徑是否正確,以及該資料表是否存在,若路徑指示容器,則回傳為真。
protected override bool IsItemContainer(string path)
{
if (PathIsDrive(path))
{
return true;
}
string[] pathChunks = ChunkPath(path);
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Table)
{
foreach (DatabaseTableInfo ti in GetTables())
{
if (string.Equals(ti.Name, tableName, StringComparison.OrdinalIgnoreCase))
{
return true;
}
} // foreach (DatabaseTableInfo...
} // if (pathChunks...
return false;
} // IsItemContainer
實作 IsItemContainer 時需要注意的事項
你的導航提供者 .NET 類別可能會宣告 System.Management.Automation.Provider.ProviderCapabilities 列舉中的 ExpandWildcard、Filter、Include 或 Exclude 等提供者能力。 在此情況下, System.Management.Automation.Provider.NavigationCmdletProvider.IsItemContainer* 的實作需要確保通過的路徑符合需求。 為此,方法應存取適當的屬性,例如 System.Management.Automation.Provider.CmdletProvider.Exclude* 屬性。
移動物品
為了支援 Move-Item cmdlet,您的導航提供者實作 System.Management.Automation.Provider.NavigationCmdletProvider.MoveItem* 方法。 此方法將參數指定的 path 項目移動到參數中路徑 destination 的容器。
範例導航提供者不會覆蓋 System.Management.Automation.Provider.NavigationCmdletProvider.MoveItem* 方法。 以下是預設實作。
實作 MoveItem 時要記住的事項
你的導航提供者 .NET 類別可能會宣告 System.Management.Automation.Provider.ProviderCapabilities 列舉中的 ExpandWildcard、Filter、Include 或 Exclude 等提供者能力。 在此情況下, System.Management.Automation.Provider.NavigationCmdletProvider.MoveItem* 的實作必須確保通過的路徑符合需求。 為此,方法應存取適當的屬性,例如 CmdletProvider.Exclude 屬性。
預設情況下,除非將 System.Management.Automation.Provider.CmdletProvider.Force* 屬性設定 true為 。 例如,FileSystem 提供者不會在現有的 C:\bar.txt 檔案上複製 C:\temp\abc.txt,除非將 System.Management.Automation.Provider.CmdletProvider.Force* 屬性設定為 true。 若參數中指定的 destination 路徑存在且為容器,則不需要 System.Management.Automation.Provider.CmdletProvider.Force* 屬性。 此時, System.Management.Automation.Provider.NavigationCmdletProvider.MoveItem* 應將參數所指示 path 的項目移至該參數所標 destination 示的容器,作為子節點。
你實作的 System.Management.Automation.Provider.NavigationCmdletProvider.MoveItem* 方法,應該在對資料庫做任何變更前,先呼叫 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.NavigationCmdletProvider.MoveItem* 方法應呼叫 System.Management.Automation.Provider.CmdletProvider.ShouldContinue 。 此方法會向使用者發送訊息,讓使用者反饋是否應該繼續操作。 您的服務提供者應致電 System.Management.Automation.Provider.CmdletProvider.ShouldContinue 作為潛在危險系統修改的額外檢查。
將動態參數附加於 Move-Item 指令小子
有時 Move-Item cmdlet 需要額外參數,這些參數會在執行時動態提供。 為了提供這些動態參數,導航提供者必須實作 System.Management.Automation.Provider.NavigationCmdletProvider.MoveItemDynamicParameters* 方法,從指定路徑的項目取得所需參數值,並回傳一個具有類似 cmdlet 類別或 System.Management.Automation.RuntimeDefinedParameterDictionary 物件的屬性與欄位的物件。
此導航提供者未實作此方法。 然而,以下程式碼是 System.Management.Automation.Provider.NavigationCmdletProvider.MoveItemDynamicParameters* 的預設實作。
相對路徑正規化
您的導航提供者實作了 System.Management.Automation.Provider.NavigationCmdletProvider.NormalizeRelativePath* 方法,將參數中標示 path 的完全限定路徑與參數指定的路徑相對於該 basePath 路徑進行正規化。 此方法回傳正規化路徑的字串表示。 若 path 參數指定不存在的路徑,則會寫入錯誤。
範例導航提供者不會覆寫此方法。 以下是預設實作。
實作 NormalizeRelativePath 需要注意的事項
你實作的 System.Management.Automation.Provider.NavigationCmdletProvider.NormalizeRelativePath* 應該會解析該 path 參數,但不一定要純粹使用語法解析。 我們鼓勵你設計此方法,利用路徑在資料庫中查詢路徑資訊,並建立符合套管及標準化路徑語法的路徑。
程式碼範例
完整範例程式碼請參閱 AccessDbProviderSample05 程式碼範例。
定義物件類型與格式
提供者可以為現有物件新增成員或定義新物件。 欲了解更多資訊,請參閱擴展物件類型與格式化。
建置 Windows PowerShell 提供者
欲了解更多資訊,請參閱 「如何註冊指令、提供者及主機應用程式」。
測試 Windows PowerShell 提供者
當你的 Windows PowerShell 提供者已註冊到 Windows PowerShell 後,你可以透過命令列執行支援的 cmdlet(包括衍生版本提供的 cmdlet)來測試。 此範例將測試範例導航提供者。
執行你的新 shell,並用
Set-Locationcmdlet 設定路徑來指示 Access 資料庫。Set-Location mydb:現在執行
Get-ChildItemcmdlet 來取得資料庫項目的清單,也就是可用的資料庫資料表。 對於每個資料表,此 cmdlet 也會取得資料表列數。Get-ChildItem | Format-Table RowCount, Name -AutoSizeRowCount Name -------- ---- 180 MSysAccessObjects 0 MSysACEs 1 MSysCmdbars 0 MSysIMEXColumns 0 MSysIMEXSpecs 0 MSysObjects 0 MSysQueries 7 MSysRelationships 8 Categories 91 Customers 9 Employees 2155 Order Details 830 Orders 77 Products 3 Shippers 29 Suppliers再次使用
Set-Locationcmdlet 設定員工資料表的位置。Set-Location Employees現在
Get-Location我們用 cmdlet 來取得 Employees 資料表的路徑。Get-LocationPath ---- mydb:\Employees現在用
Get-ChildItemcmdlet 輸出到Format-Tablecmdlet 上。 這組 cmdlet 用來取得 Employees 資料表的項目,也就是資料表的列。 它們的格式依照指令碼(cmdlet)Format-Table所規定。Get-ChildItem | Format-Table RowNumber, PSIsContainer, Data -AutoSizeRowNumber PSIsContainer Data --------- -------------- ---- 0 False System.Data.DataRow 1 False System.Data.DataRow 2 False System.Data.DataRow 3 False System.Data.DataRow 4 False System.Data.DataRow 5 False System.Data.DataRow 6 False System.Data.DataRow 7 False System.Data.DataRow 8 False System.Data.DataRow你現在可以執行
Get-Itemcmdlet 來取得 Employees 資料表第 0 列的項目。Get-Item 0PSPath : AccessDB::C:\PS\Northwind.mdb\Employees\0 PSParentPath : AccessDB::C:\PS\Northwind.mdb\Employees PSChildName : 0 PSDrive : mydb PSProvider : System.Management.Automation.ProviderInfo PSIsContainer : False Data : System.Data.DataRow RowNumber : 0再次使用
Get-Itemcmdlet 取得第 0 列項目的員工資料。(Get-Item 0).DataEmployeeID : 1 LastName : Davis FirstName : Sara Title : Sales Representative TitleOfCourtesy : Ms. BirthDate : 12/8/1968 12:00:00 AM HireDate : 5/1/1992 12:00:00 AM Address : 4567 Main Street Apt. 2A City : Buffalo Region : NY PostalCode : 98052 Country : USA HomePhone : (206) 555-9857 Extension : 5467 Photo : EmpID1.bmp Notes : Education includes a BA in psychology from Colorado State University. She also completed "The Art of the Cold Call." Nancy is a member of Toastmasters International. ReportsTo : 2