编写项提供程序

本主题介绍如何实现访问和作数据存储中的项的 Windows PowerShell 提供程序的方法。 若要访问项,提供程序必须派生自 System.Management.Automation.Provider.ItemCmdletProvider 类。

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

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

实现项方法

System.Management.Automation.Provider.ItemCmdletProvider 类公开了几种可用于访问和作数据存储中的项的方法。 有关这些方法的完整列表,请参阅 ItemCmdletProvider 方法。 在此示例中,我们将实现其中四种方法。 System.Management.Automation.Provider.ItemCmdletProvider.GetItem* 指定路径处获取项。 System.Management.Automation.Provider.ItemCmdletProvider.SetItem* 设置指定项的值。 System.Management.Automation.Provider.ItemCmdletProvider.ItemExists* 检查指定路径是否存在项。 System.Management.Automation.Provider.ItemCmdletProvider.IsValidPath* 检查路径以查看它是否映射到数据存储中的位置。

注释

本主题基于 Windows PowerShell 提供程序快速入门中的信息。 本主题不介绍如何设置提供程序项目的基础知识,或者如何实现从创建和删除驱动器的 System.Management.Automation.Provider.DriveCmdletProvider 类继承的方法。

声明提供程序类

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

[CmdletProvider("AccessDB", ProviderCapabilities.None)]

   public class AccessDBProvider : ItemCmdletProvider
   {

  }

实现 GetItem

当用户在提供程序上调用 Microsoft.PowerShell.Commands.GetItemCommand cmdlet 时,PowerShell 引擎将调用 System.Management.Automation.Provider.ItemCmdletProvider.GetItem*。 该方法返回指定路径处的项。 在 Access 数据库示例中,该方法检查项是驱动器本身、数据库中的表还是数据库中的行。 该方法通过调用 System.Management.Automation.Provider.CmdletProvider.WriteItemObject* 方法将项发送到 PowerShell 引擎。

protected override void GetItem(string path)
      {
          // check if the path represented is a drive
          if (PathIsDrive(path))
          {
              WriteItemObject(this.PSDriveInfo, path, true);
              return;
          }// if (PathIsDrive...

           // Get table name and row information from the path and do
           // necessary actions
           string tableName;
           int rowNumber;

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

           if (type == PathType.Table)
           {
               DatabaseTableInfo table = GetTable(tableName);
               WriteItemObject(table, path, true);
           }
           else if (type == PathType.Row)
           {
               DatabaseRowInfo row = GetRow(tableName, rowNumber);
               WriteItemObject(row, path, false);
           }
           else
           {
               ThrowTerminatingInvalidPathException(path);
           }

       }

实现 SetItem

当用户调用 Microsoft.PowerShell.Commands.SetItemCommand cmdlet 时,PowerShell 引擎调用 System.Management.Automation.Provider.ItemCmdletProvider.SetItem* 方法。 它设置指定路径处的项的值。

在 Access 数据库示例中,仅当该项为行时设置项的值是有意义的,因此当项不是行时,该方法将引发 NotSupportedException

protected override void SetItem(string path, object values)
       {
           // Get type, table name and row number from the path specified
           string tableName;
           int rowNumber;

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

           if (type != PathType.Row)
           {
               WriteError(new ErrorRecord(new NotSupportedException(
                     "SetNotSupported"), "",
                  ErrorCategory.InvalidOperation, path));

               return;
           }

           // Get in-memory representation of table
           OdbcDataAdapter da = GetAdapterForTable(tableName);

           if (da == null)
           {
               return;
           }
           DataSet ds = GetDataSetForTable(da, tableName);
           DataTable table = GetDataTable(ds, tableName);

           if (rowNumber >= table.Rows.Count)
           {
               // The specified row number has to be available. If not
               // NewItem has to be used to add a new row
               throw new ArgumentException("Row specified is not available");
           } // if (rowNum...

           string[] colValues = (values as string).Split(',');

           // set the specified row
           DataRow row = table.Rows[rowNumber];

           for (int i = 0; i < colValues.Length; i++)
           {
               row[i] = colValues[i];
           }

           // Update the table
           if (ShouldProcess(path, "SetItem"))
           {
               da.Update(ds, tableName);
           }

       }

实现 ItemExists

当用户调用 Microsoft.PowerShell.Commands.TestPathCommand cmdlet 时,PowerShell 引擎调用 System.Management.Automation.Provider.ItemCmdletProvider.ItemExists* 方法。 该方法确定指定路径中是否存在项。 如果项存在,该方法通过调用 System.Management.Automation.Provider.CmdletProvider.WriteItemObject*将其传回 PowerShell 引擎。

protected override bool ItemExists(string path)
       {
           // check if the path represented is a drive
           if (PathIsDrive(path))
           {
               return true;
           }

           // Obtain type, table name and row number from path
           string tableName;
           int rowNumber;

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

           DatabaseTableInfo table = GetTable(tableName);

           if (type == PathType.Table)
           {
               // if specified path represents a table then DatabaseTableInfo
               // object for the same should exist
               if (table != null)
               {
                   return true;
               }
           }
           else if (type == PathType.Row)
           {
               // if specified path represents a row then DatabaseTableInfo should
               // exist for the table and then specified row number must be within
               // the maximum row count in the table
               if (table != null && rowNumber < table.RowCount)
               {
                   return true;
               }
           }

           return false;

       }

实现 IsValidPath

System.Management.Automation.Provider.ItemCmdletProvider.IsValidPath* 方法检查指定的路径是否对当前提供程序有效。 它不检查路径中是否存在项。

protected override bool IsValidPath(string path)
       {
           bool result = true;

           // check if the path is null or empty
           if (String.IsNullOrEmpty(path))
           {
               result = false;
           }

           // convert all separators in the path to a uniform one
           path = NormalizePath(path);

           // split the path into individual chunks
           string[] pathChunks = path.Split(pathSeparator.ToCharArray());

           foreach (string pathChunk in pathChunks)
           {
               if (pathChunk.Length == 0)
               {
                   result = false;
               }
           }
           return result;
       }

后续步骤

典型的实际提供商能够支持包含其他项的项目,以及将项从一个路径移到驱动器中的另一个路径。 有关支持容器的提供程序的示例,请参阅 编写容器提供程序。 有关支持移动项的提供程序的示例,请参阅 编写导航提供程序

另请参阅

编写容器提供程序

编写导航提供程序

Windows PowerShell 提供程序概述