本主题介绍如何实现访问和作数据存储中的项的 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;
}
后续步骤
典型的实际提供商能够支持包含其他项的项目,以及将项从一个路径移到驱动器中的另一个路径。 有关支持容器的提供程序的示例,请参阅 编写容器提供程序。 有关支持移动项的提供程序的示例,请参阅 编写导航提供程序。