编写导航提供程序

本主题介绍如何实现支持嵌套容器(多级数据存储)、移动项和相对路径的 Windows PowerShell 提供程序的方法。 导航提供程序必须派生自 System.Management.Automation.Provider.NavigationCmdletProvider 类。

本主题示例中的提供程序使用 Access 数据库作为其数据存储。 有几个帮助程序方法和类用于与数据库交互。 有关包含帮助程序方法的完整示例,请参阅 AccessDBProviderSample05

有关 Windows PowerShell 提供程序的详细信息,请参阅 Windows PowerShell 提供程序概述

实现导航方法

System.Management.Automation.Provider.NavigationCmdletProvider 类实现支持嵌套容器、相对路径和移动项的方法。 有关这些方法的完整列表,请参阅 NavigationCmdletProvider 方法

注释

本主题基于 Windows PowerShell 提供程序快速入门中的信息。 本主题不介绍如何设置提供程序项目的基础知识,或者如何实现从创建和删除驱动器的 System.Management.Automation.Provider.DriveCmdletProvider 类继承的方法。 本主题也不介绍如何实现由 System.Management.Automation.Provider.ItemCmdletProviderSystem.Management.Automation.Provider.ContainerCmdletProvider 类公开的方法。 有关如何实现项 cmdlet 的示例,请参阅 编写项提供程序。 有关如何实现容器 cmdlet 的示例,请参阅 编写容器提供程序

声明提供程序类

声明提供程序以派生自 System.Management.Automation.Provider.NavigationCmdletProvider 类,并使用 System.Management.Automation.Provider.CmdletProviderAttribute对其进行修饰。

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

   }

实现 IsItemContainer

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;
      }

实现 GetChildName

System.Management.Automation.Provider.NavigationCmdletProvider.GetChildName* 方法获取指定路径上子项的名称属性。 如果指定路径上的项不是容器的子级,则此方法应返回路径。

protected override string GetChildName(string path)
       {
           if (PathIsDrive(path))
           {
               return path;
           }

           string tableName;
           int rowNumber;

           PathType type = GetNamesFromPath(path, out tableName, out rowNumber);

           if (type == PathType.Table)
           {
               return tableName;
           }
           else if (type == PathType.Row)
           {
               return rowNumber.ToString(CultureInfo.CurrentCulture);
           }
           else
           {
               ThrowTerminatingInvalidPathException(path);
           }

           return null;
       }

实现 GetParentPath

System.Management.Automation.Provider.NavigationCmdletProvider.GetParentPath* 方法获取指定路径处项的父级的路径。 如果指定路径中的项是数据存储的根目录(因此没有父项),则此方法应返回根路径。

protected override string GetParentPath(string path, string root)
       {
           // If root is specified then the path has to contain
           // the root. If not nothing should be returned
           if (!String.IsNullOrEmpty(root))
           {
               if (!path.Contains(root))
               {
                   return null;
               }
           }

           return path.Substring(0, path.LastIndexOf(pathSeparator, StringComparison.OrdinalIgnoreCase));
       }

实现 MakePath

System.Management.Automation.Provider.NavigationCmdletProvider.MakePath* 方法联接指定的父路径和指定子路径来创建提供程序内部路径(有关提供程序可支持的路径类型的信息,请参阅 Windows PowerShell 提供程序概述。 当用户调用 Microsoft.PowerShell.Commands.JoinPathCommand cmdlet 时,PowerShell 引擎将调用此方法。

protected override string MakePath(string parent, string child)
       {
           string result;

           string normalParent = NormalizePath(parent);
           normalParent = RemoveDriveFromPath(normalParent);
           string normalChild = NormalizePath(child);
           normalChild = RemoveDriveFromPath(normalChild);

           if (String.IsNullOrEmpty(normalParent) && String.IsNullOrEmpty(normalChild))
           {
               result = String.Empty;
           }
           else if (String.IsNullOrEmpty(normalParent) && !String.IsNullOrEmpty(normalChild))
           {
               result = normalChild;
           }
           else if (!String.IsNullOrEmpty(normalParent) && String.IsNullOrEmpty(normalChild))
           {
               if (normalParent.EndsWith(pathSeparator, StringComparison.OrdinalIgnoreCase))
               {
                   result = normalParent;
               }
               else
               {
                   result = normalParent + pathSeparator;
               }
           } // else if (!String...
           else
           {
               if (!normalParent.Equals(String.Empty) &&
                   !normalParent.EndsWith(pathSeparator, StringComparison.OrdinalIgnoreCase))
               {
                   result = normalParent + pathSeparator;
               }
               else
               {
                   result = normalParent;
               }

               if (normalChild.StartsWith(pathSeparator, StringComparison.OrdinalIgnoreCase))
               {
                   result += normalChild.Substring(1);
               }
               else
               {
                   result += normalChild;
               }
           } // else

           return result;
       }

实现 NormalizeRelativePath

System.Management.Automation.Provider.NavigationCmdletProvider.NormalizeRelativePath* 方法采用 pathbasepath 参数,并返回与 path 参数和相对于 basepath 参数等效的规范化路径。

protected override string NormalizeRelativePath(string path,
                                                            string basepath)
       {
           // Normalize the paths first
           string normalPath = NormalizePath(path);
           normalPath = RemoveDriveFromPath(normalPath);
           string normalBasePath = NormalizePath(basepath);
           normalBasePath = RemoveDriveFromPath(normalBasePath);

           if (String.IsNullOrEmpty(normalBasePath))
           {
               return normalPath;
           }
           else
           {
               if (!normalPath.Contains(normalBasePath))
               {
                   return null;
               }

               return normalPath.Substring(normalBasePath.Length + pathSeparator.Length);
           }
       }

实现 MoveItem

System.Management.Automation.Provider.NavigationCmdletProvider.MoveItem* 方法将项从指定路径移动到指定的目标路径。 当用户调用 Microsoft.PowerShell.Commands.MoveItemCommand cmdlet 时,PowerShell 引擎将调用此方法。

protected override void MoveItem(string path, string destination)
       {
           // Get type, table name and rowNumber from the path
           string tableName, destTableName;
           int rowNumber, destRowNumber;

           PathType type = GetNamesFromPath(path, out tableName, out rowNumber);

           PathType destType = GetNamesFromPath(destination, out destTableName,
                                    out destRowNumber);

           if (type == PathType.Invalid)
           {
               ThrowTerminatingInvalidPathException(path);
           }

           if (destType == PathType.Invalid)
           {
               ThrowTerminatingInvalidPathException(destination);
           }

           if (type == PathType.Table)
           {
               ArgumentException e = new ArgumentException("Move not supported for tables");

               WriteError(new ErrorRecord(e, "MoveNotSupported",
                   ErrorCategory.InvalidArgument, path));

               throw e;
           }
           else
           {
               OdbcDataAdapter da = GetAdapterForTable(tableName);
               if (da == null)
               {
                   return;
               }

               DataSet ds = GetDataSetForTable(da, tableName);
               DataTable table = GetDataTable(ds, tableName);

               OdbcDataAdapter dda = GetAdapterForTable(destTableName);
               if (dda == null)
               {
                   return;
               }

               DataSet dds = GetDataSetForTable(dda, destTableName);
               DataTable destTable = GetDataTable(dds, destTableName);
               DataRow row = table.Rows[rowNumber];

               if (destType == PathType.Table)
               {
                   DataRow destRow = destTable.NewRow();

                   destRow.ItemArray = row.ItemArray;
               }
               else
               {
                   DataRow destRow = destTable.Rows[destRowNumber];

                   destRow.ItemArray = row.ItemArray;
               }

               // Update the changes
               if (ShouldProcess(path, "MoveItem"))
               {
                   WriteItemObject(row, path, false);
                   dda.Update(dds, destTableName);
               }
           }
       }

另请参阅

编写容器提供程序

Windows PowerShell 提供程序概述