创建 Windows PowerShell 导航提供者

本主题描述如何创建一个 Windows PowerShell 导航工具,用于导航数据存储。 这种类型的提供者支持递归命令、嵌套容器和相对路径。

注释

您可以使用 Windows Vista 和 .NET Framework 3.0 运行时组件的 Microsoft Windows 软件开发工具包下载该提供者的 C# 源文件(AccessDBSampleProvider05.cs)。 有关下载说明,请参见 《如何安装Windows PowerShell》和《Windows PowerShell SDK》。 下载的源文件可在 <PowerShell Samples> 目录中获取。 有关其他 Windows PowerShell 提供者实现的更多信息,请参见 “设计你的 Windows PowerShell 提供者”。

这里描述的提供者允许用户将 Access 数据库作为驱动器管理,从而能够导航到数据库中的数据表。 在创建自己的导航提供者时,你可以实现一些方法,比如要求导航必须有驱动器合格的路径,规范化相对路径,移动数据存储中的项目,以及获取子名称、获取项目的父路径,并测试项目是否是容器的方法。

注意

请注意,这种设计假设数据库有一个带有名称 ID 的字段,且字段类型为 LongInteger。

定义 Windows PowerShell 提供者

Windows PowerShell 导航提供者必须创建一个从 System.Management.Automation.Provider.NavigationCmdletProvider 基类衍生的 .NET 类。 以下是本节中描述的导航提供者的类定义。

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

注意,在此提供者中, System.Management.Automation.Provider.CmdletProviderAttribute 属性包含两个参数。 第一个参数指定了 Windows PowerShell 所用提供者的用户友好名称。 第二个参数指定了 Windows PowerShell 在命令处理过程中向 Windows PowerShell 运行时暴露的具体功能。 对于该提供者,没有添加任何 Windows PowerShell 特定的功能。

定义基础功能

如《 设计你的 PS 提供者》中所述, 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 导航提供者使用提供者内部 Windows PowerShell 路径来导航数据存储中的项。 要创建提供者-内部路径,提供者必须实现 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法,以支持 Combine-Path cmdlet 调用。 该方法将父路径和子路径合并为提供者-内部路径,使用提供者专用的路径分隔符区分父子路径。

默认实现采用带有“/”或“\”的路径分隔符,将路径分隔符归一化为“\”,将父路径和子路径部分与分隔符合并,然后返回包含合并路径的字符串。

该导航提供者不实现该方法。 然而,以下代码是 System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法的默认实现。

实现MakePath需要注意的事项

以下条件可能适用于您对 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* 方法,以判断指定路径是否指向容器。 如果路径代表容器,则返回为真;否则返回为假。 用户需要这种方法才能使用 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 命令,导航提供者实现了 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.WithContinue ,作为潜在危险系统修改的额外检查。

将动态参数附加到 Move-Item cmdlet

有时 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(包括通过派生提供)来测试。 本示例将测试示例导航提供者。

  1. 运行你的新shell,用 Set-Location cmdlet设置路径以指示Access数据库。

    Set-Location mydb:
    
  2. 现在运行 Get-ChildItem cmdlet 以获取数据库项目列表,也就是可用的数据库表。 对于每个表,该 cmdlet 还检索表行数。

    Get-ChildItem | Format-Table RowCount, Name -AutoSize
    
    RowCount   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
    
  3. 再次使用 Set-Location 命令子设置员工数据表的位置。

    Set-Location Employees
    
  4. 现在我们用 Get-Location cmdlet获取Employees表的路径。

    Get-Location
    
    Path
    ----
    mydb:\Employees
    
  5. 现在用 Get-ChildItem 管道传输到 Format-Table 指令的指令令。 这组 cmdlet 用于获取 Employees 数据表的项,即表行。 它们的格式按照指令符(cmdlet) Format-Table 指定。

    Get-ChildItem | Format-Table RowNumber, PSIsContainer, Data -AutoSize
    
    RowNumber   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
    
  6. 你现在可以运行 Get-Item cmdlet 来获取 Employees 数据表第 0 行的项目。

    Get-Item 0
    
    PSPath        : 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
    
  7. 再次使用 Get-Item 命令小工具检索第0行项目的员工数据。

    (Get-Item 0).Data
    
    EmployeeID      : 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
    

另请参阅

创建 Windows PowerShell 提供者

设计您的Windows PowerShell提供者

扩展对象类型与格式化

Implement a Container Windows PowerShell provider

如何注册 Cmdlet、提供者和托管应用程序

Windows PowerShell 程序员指南

Windows PowerShell SDK