Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tema se describe cómo crear un proveedor de Windows PowerShell que permita al usuario manipular el contenido de los elementos de un almacén de datos. Como consecuencia, un proveedor que puede manipular el contenido de los elementos se conoce como proveedor de contenido de Windows PowerShell.
Nota:
Puede descargar el archivo de código fuente de C# (AccessDBSampleProvider06.cs) para este proveedor mediante el Kit de desarrollo de software de Microsoft Windows para Windows Vista y componentes en tiempo de ejecución de .NET Framework 3.0. Para obtener instrucciones de descarga, consulte Cómo instalar Windows PowerShell y Descargar el SDK de Windows PowerShell. Los archivos de código fuente descargados están disponibles en el directorio>ejemplos de PowerShell de<. Para obtener más información sobre otras implementaciones del proveedor de Windows PowerShell, consulte Diseño del proveedor de Windows PowerShell.
Definir la clase de proveedor de contenido de Windows PowerShell
Un proveedor de contenido de Windows PowerShell debe crear una clase .NET que admita la interfaz System.Management.Automation.Provider.IContentCmdletProvider. Esta es la definición de clase para el proveedor de elementos descrito en esta sección.
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : NavigationCmdletProvider, IContentCmdletProvider
Tenga en cuenta que, en esta definición de clase, el atributo System.Management.Automation.Provider.CmdletProviderAttribute incluye dos parámetros. El primer parámetro especifica un nombre descriptivo para el proveedor que usa Windows PowerShell. El segundo parámetro especifica las funcionalidades específicas de Windows PowerShell que el proveedor expone al entorno de ejecución de Windows PowerShell durante el procesamiento de comandos. Para este proveedor, no se han agregado funcionalidades específicas de Windows PowerShell.
Definir la funcionalidad de la clase base
Tal y como se describe en Diseñar el proveedor de Windows PowerShell, la clase System.Management.Automation.Provider.NavigationCmdletProvider deriva de otras clases que proporcionan distintas funcionalidades del proveedor. Un proveedor de contenido de Windows PowerShell, por lo tanto, normalmente define toda la funcionalidad proporcionada por esas clases.
Para obtener más información sobre cómo implementar la funcionalidad para agregar información de inicialización específica de la sesión y para liberar recursos que usa el proveedor, vea Creación de un proveedor básico de Windows PowerShell. Sin embargo, la mayoría de los proveedores, incluido el proveedor descrito aquí, pueden usar la implementación predeterminada de esta funcionalidad proporcionada por Windows PowerShell.
Para acceder al almacén de datos, el proveedor debe implementar los métodos de la clase base system.Management.Automation.Provider.DriveCmdletProvider . Para obtener más información sobre cómo implementar estos métodos, vea Creación de un proveedor de unidades de Windows PowerShell.
Para manipular los elementos de un almacén de datos, como obtener, establecer y borrar elementos, el proveedor debe implementar los métodos proporcionados por la clase base System.Management.Automation.Provider.ItemCmdletProvider. Para obtener más información sobre cómo implementar estos métodos, vea Creación de un proveedor de elementos de Windows PowerShell.
Para trabajar en almacenes de datos de varias capas, el proveedor debe implementar los métodos proporcionados por la clase base System.Management.Automation.Provider.ContainerCmdletProvider. Para obtener más información sobre cómo implementar estos métodos, vea Creación de un proveedor de contenedores de Windows PowerShell.
Para admitir comandos recursivos, contenedores anidados y rutas de acceso relativas, el proveedor debe implementar la clase base System.Management.Automation.Provider.NavigationCmdletProvider. Además, este proveedor de contenido de Windows PowerShell puede asociar System.Management.Automation.Provider.IContentCmdletProvider interfaz a la interfaz System.Management.Automation.Provider.NavigationCmdletProvider clase base y, por tanto, debe implementar los métodos proporcionados por esa clase. Para obtener más información, consulte implementación de esos métodos, consulte Implementar un proveedor de Windows PowerShell de navegación.
Implementación de un lector de contenido
Para leer contenido de un elemento, un proveedor debe implementar una clase de lector de contenido que derive de System.Management.Automation.Provider.IContentReader. El lector de contenido de este proveedor permite el acceso al contenido de una fila de una tabla de datos. La clase de lector de contenido define un método Read que recupera los datos de la fila indicada y devuelve una lista que representa esos datos, un método Seek que mueve el lector de contenido, un método Close que cierra el lector de contenido y un método Dispose.
public class AccessDBContentReader : IContentReader
{
// A provider instance is required so as to get "content"
private AccessDBProvider provider;
private string path;
private long currentOffset;
internal AccessDBContentReader(string path, AccessDBProvider provider)
{
this.path = path;
this.provider = provider;
}
/// <summary>
/// Read the specified number of rows from the source.
/// </summary>
/// <param name="readCount">The number of items to
/// return.</param>
/// <returns>An array of elements read.</returns>
public IList Read(long readCount)
{
// Read the number of rows specified by readCount and increment
// offset
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
Collection<DatabaseRowInfo> rows =
provider.GetRows(tableName);
Collection<DataRow> results = new Collection<DataRow>();
if (currentOffset < 0 || currentOffset >= rows.Count)
{
return null;
}
int rowsRead = 0;
while (rowsRead < readCount && currentOffset < rows.Count)
{
results.Add(rows[(int)currentOffset].Data);
rowsRead++;
currentOffset++;
}
return results;
} // Read
/// <summary>
/// Moves the content reader specified number of rows from the
/// origin
/// </summary>
/// <param name="offset">Number of rows to offset</param>
/// <param name="origin">Starting row from which to offset</param>
public void Seek(long offset, System.IO.SeekOrigin origin)
{
// get the number of rows in the table which will help in
// calculating current position
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
throw new ArgumentException("Path specified must represent a table or a row :" + path);
}
if (type == PathType.Table)
{
Collection<DatabaseRowInfo> rows = provider.GetRows(tableName);
int numRows = rows.Count;
if (offset > rows.Count)
{
throw new
ArgumentException(
"Offset cannot be greater than the number of rows available"
);
}
if (origin == System.IO.SeekOrigin.Begin)
{
// starting from Beginning with an index 0, the current offset
// has to be advanced to offset - 1
currentOffset = offset - 1;
}
else if (origin == System.IO.SeekOrigin.End)
{
// starting from the end which is numRows - 1, the current
// offset is so much less than numRows - 1
currentOffset = numRows - 1 - offset;
}
else
{
// calculate from the previous value of current offset
// advancing forward always
currentOffset += offset;
}
} // if (type...
else
{
// for row, the offset will always be set to 0
currentOffset = 0;
}
} // Seek
/// <summary>
/// Closes the content reader, so all members are reset
/// </summary>
public void Close()
{
Dispose();
} // Close
/// <summary>
/// Dispose any resources being used
/// </summary>
public void Dispose()
{
Seek(0, System.IO.SeekOrigin.Begin);
GC.SuppressFinalize(this);
} // Dispose
} // AccessDBContentReader
Implementación de un escritor de contenido
Para escribir contenido en un elemento, un proveedor debe implementar una clase de escritor de contenido derivada de System.Management.Automation.Provider.IContentWriter. La clase content writer define un método Write que escribe el contenido de fila especificado, un método Seek que mueve el escritor de contenido, un método Close que cierra el escritor de contenido y un método Dispose.
public class AccessDBContentWriter : IContentWriter
{
// A provider instance is required so as to get "content"
private AccessDBProvider provider;
private string path;
private long currentOffset;
internal AccessDBContentWriter(string path, AccessDBProvider provider)
{
this.path = path;
this.provider = provider;
}
/// <summary>
/// Write the specified row contents in the source
/// </summary>
/// <param name="content"> The contents to be written to the source.
/// </param>
/// <returns>An array of elements which were successfully written to
/// the source</returns>
///
public IList Write(IList content)
{
if (content == null)
{
return null;
}
// Get the total number of rows currently available it will
// determine how much to overwrite and how much to append at
// the end
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Table)
{
OdbcDataAdapter da = provider.GetAdapterForTable(tableName);
if (da == null)
{
return null;
}
DataSet ds = provider.GetDataSetForTable(da, tableName);
DataTable table = provider.GetDataTable(ds, tableName);
string[] colValues = (content[0] as string).Split(',');
// set the specified row
DataRow row = table.NewRow();
for (int i = 0; i < colValues.Length; i++)
{
if (!String.IsNullOrEmpty(colValues[i]))
{
row[i] = colValues[i];
}
}
//table.Rows.InsertAt(row, rowNumber);
// Update the table
table.Rows.Add(row);
da.Update(ds, tableName);
}
else
{
throw new InvalidOperationException("Operation not supported. Content can be added only for tables");
}
return null;
} // Write
/// <summary>
/// Moves the content reader specified number of rows from the
/// origin
/// </summary>
/// <param name="offset">Number of rows to offset</param>
/// <param name="origin">Starting row from which to offset</param>
public void Seek(long offset, System.IO.SeekOrigin origin)
{
// get the number of rows in the table which will help in
// calculating current position
string tableName;
int rowNumber;
PathType type = provider.GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
throw new ArgumentException("Path specified should represent either a table or a row : " + path);
}
Collection<DatabaseRowInfo> rows =
provider.GetRows(tableName);
int numRows = rows.Count;
if (offset > rows.Count)
{
throw new
ArgumentException(
"Offset cannot be greater than the number of rows available"
);
}
if (origin == System.IO.SeekOrigin.Begin)
{
// starting from Beginning with an index 0, the current offset
// has to be advanced to offset - 1
currentOffset = offset - 1;
}
else if (origin == System.IO.SeekOrigin.End)
{
// starting from the end which is numRows - 1, the current
// offset is so much less than numRows - 1
currentOffset = numRows - 1 - offset;
}
else
{
// calculate from the previous value of current offset
// advancing forward always
currentOffset += offset;
}
} // Seek
/// <summary>
/// Closes the content reader, so all members are reset
/// </summary>
public void Close()
{
Dispose();
} // Close
/// <summary>
/// Dispose any resources being used
/// </summary>
public void Dispose()
{
Seek(0, System.IO.SeekOrigin.Begin);
GC.SuppressFinalize(this);
} // Dispose
} // AccessDBContentWriter
Recuperación del lector de contenido
Para obtener contenido de un elemento, el proveedor debe implementar el System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* para admitir el cmdlet Get-Content
. Este método devuelve el lector de contenido del elemento ubicado en la ruta de acceso especificada. A continuación, se puede abrir el objeto lector para leer el contenido.
Esta es la implementación de System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* para este método para este proveedor.
public IContentReader GetContentReader(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be obtained only for tables");
}
return new AccessDBContentReader(path, this);
} // GetContentReader
public IContentReader GetContentReader(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be obtained only for tables");
}
return new AccessDBContentReader(path, this);
} // GetContentReader
Cosas que recordar sobre la implementación de GetContentReader
Las condiciones siguientes pueden aplicarse a una implementación de System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader*:
Al definir la clase de proveedor, un proveedor de contenido de Windows PowerShell podría declarar funcionalidades de proveedor de ExpandWildcards, Filter, Include o Exclude, de la enumeración System.Management.Automation.Provider.ProviderCap abilities. En estos casos, la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* debe asegurarse de que la ruta de acceso pasada al método cumple los requisitos de las funcionalidades especificadas. Para ello, el método debe tener acceso a la propiedad adecuada, por ejemplo, las propiedades System.Management.Automation.Provider.CmdletProvider.Exclude* y System.Management.Automation.Provider.CmdletProvider.Include*.
De forma predeterminada, las invalidaciones de este método no deben recuperar un lector para los objetos ocultos del usuario a menos que la propiedad System.Management.Automation.Provider.CmdletProvider.Force* esté establecida en
true
. Se debe escribir un error si la ruta de acceso representa un elemento oculto del usuario y System.Management.Automation.Provider.CmdletProvider.Force* está establecido enfalse
.
Asociación de parámetros dinámicos al cmdlet de Get-Content
El cmdlet Get-Content
puede requerir parámetros adicionales que se especifican dinámicamente en tiempo de ejecución. Para proporcionar estos parámetros dinámicos, el proveedor de contenido de Windows PowerShell debe implementar el método System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters*. Este método recupera parámetros dinámicos para el elemento en la ruta de acceso indicada y devuelve un objeto que tiene propiedades y campos con atributos de análisis similares a una clase de cmdlet o un objeto System.Management.Automation.RuntimeDefinedParameterDictionary. El entorno de ejecución de Windows PowerShell usa el objeto devuelto para agregar los parámetros al cmdlet .
Este proveedor de contenedores de Windows PowerShell no implementa este método. Sin embargo, el código siguiente es la implementación predeterminada de este método.
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
Recuperación del escritor de contenido
Para escribir contenido en un elemento, el proveedor debe implementar el System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* para admitir los cmdlets Set-Content
y Add-Content
. Este método devuelve el escritor de contenido para el elemento ubicado en la ruta de acceso especificada.
Esta es la implementación de System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* para este método.
public IContentWriter GetContentWriter(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be added only to tables");
}
return new AccessDBContentWriter(path, this);
}
public IContentWriter GetContentWriter(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type == PathType.Invalid)
{
ThrowTerminatingInvalidPathException(path);
}
else if (type == PathType.Row)
{
throw new InvalidOperationException("contents can be added only to tables");
}
return new AccessDBContentWriter(path, this);
}
Cosas que recordar sobre la implementación de GetContentWriter
Las condiciones siguientes pueden aplicarse a la implementación de System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter*:
Al definir la clase de proveedor, un proveedor de contenido de Windows PowerShell podría declarar funcionalidades de proveedor de ExpandWildcards, Filter, Include o Exclude, de la enumeración System.Management.Automation.Provider.ProviderCap abilities. En estos casos, la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* debe asegurarse de que la ruta de acceso pasada al método cumple los requisitos de las funcionalidades especificadas. Para ello, el método debe tener acceso a la propiedad adecuada, por ejemplo, las propiedades System.Management.Automation.Provider.CmdletProvider.Exclude* y System.Management.Automation.Provider.CmdletProvider.Include*.
De forma predeterminada, las invalidaciones de este método no deben recuperar un escritor para los objetos ocultos del usuario a menos que la propiedad System.Management.Automation.Provider.CmdletProvider.Force* esté establecida en
true
. Se debe escribir un error si la ruta de acceso representa un elemento oculto del usuario y System.Management.Automation.Provider.CmdletProvider.Force* está establecido enfalse
.
Adjuntar parámetros dinámicos a los cmdlets de Add-Content y Set-Content
Los cmdlets Add-Content
y Set-Content
pueden requerir parámetros dinámicos adicionales que se agregan a un entorno de ejecución. Para proporcionar estos parámetros dinámicos, el proveedor de contenido de Windows PowerShell debe implementar el método System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* para controlar estos parámetros. Este método recupera parámetros dinámicos para el elemento en la ruta de acceso indicada y devuelve un objeto que tiene propiedades y campos con atributos de análisis similares a una clase de cmdlet o un objeto System.Management.Automation.RuntimeDefinedParameterDictionary. El entorno de ejecución de Windows PowerShell usa el objeto devuelto para agregar los parámetros a los cmdlets.
Este proveedor de contenedores de Windows PowerShell no implementa este método. Sin embargo, el código siguiente es la implementación predeterminada de este método.
public object GetContentWriterDynamicParameters(string path)
{
return null;
}
Borrar contenido
El proveedor de contenido implementa el método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* compatible con el cmdlet Clear-Content
. Este método quita el contenido del elemento en la ruta de acceso especificada, pero deja intacto el elemento.
Esta es la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* para este proveedor.
public void ClearContent(string path)
{
string tableName;
int rowNumber;
PathType type = GetNamesFromPath(path, out tableName, out rowNumber);
if (type != PathType.Table)
{
WriteError(new ErrorRecord(
new InvalidOperationException("Operation not supported. Content can be cleared only for table"),
"NotValidRow", ErrorCategory.InvalidArgument,
path));
return;
}
OdbcDataAdapter da = GetAdapterForTable(tableName);
if (da == null)
{
return;
}
DataSet ds = GetDataSetForTable(da, tableName);
DataTable table = GetDataTable(ds, tableName);
// Clear contents at the specified location
for (int i = 0; i < table.Rows.Count; i++)
{
table.Rows[i].Delete();
}
if (ShouldProcess(path, "ClearContent"))
{
da.Update(ds, tableName);
}
} // ClearContent
Cosas que recordar sobre la implementación de ClearContent
Las condiciones siguientes pueden aplicarse a una implementación de System.Management.Automation.Provider.IContentCmdletProvider.ClearContent*:
Al definir la clase de proveedor, un proveedor de contenido de Windows PowerShell podría declarar funcionalidades de proveedor de ExpandWildcards, Filter, Include o Exclude, de la enumeración System.Management.Automation.Provider.ProviderCap abilities. En estos casos, la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* debe asegurarse de que la ruta de acceso pasada al método cumple los requisitos de las funcionalidades especificadas. Para ello, el método debe tener acceso a la propiedad adecuada, por ejemplo, las propiedades System.Management.Automation.Provider.CmdletProvider.Exclude* y System.Management.Automation.Provider.CmdletProvider.Include*.
De forma predeterminada, las invalidaciones de este método no deben borrar el contenido de los objetos ocultos del usuario a menos que la propiedad System.Management.Automation.Provider.CmdletProvider.Force* esté establecida en
true
. Se debe escribir un error si la ruta de acceso representa un elemento oculto del usuario y System.Management.Automation.Provider.CmdletProvider.Force* está establecido enfalse
.La implementación del método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* debe llamar a System.Management.Automation.Provider.CmdletProvider.ShouldProcess y comprobar su valor devuelto antes de realizar cambios en el almacén de datos. Este método se usa para confirmar la ejecución de una operación cuando se realiza un cambio en el almacén de datos, como borrar contenido. El método System.Management.Automation.Provider.CmdletProvider.ShouldProcess envía el nombre del recurso que se va a cambiar al usuario, con el tiempo de ejecución de Windows PowerShell que controla cualquier configuración de línea de comandos o variables de preferencia para determinar qué se debe mostrar.
Después de la llamada a System.Management.Automation.Provider.CmdletProvider.ShouldProcess devuelve
true
, el método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* debe llamar al método System.Management.Automation.Provider.CmdletProvider.ShouldContinue. Este método envía un mensaje al usuario para permitir que los comentarios comprueben si se debe continuar la operación. La llamada a System.Management.Automation.Provider.CmdletProvider.ShouldContinue permite una comprobación adicional de las modificaciones del sistema potencialmente peligrosas.
Asociación de parámetros dinámicos al cmdlet de Clear-Content
El cmdlet Clear-Content
podría requerir parámetros dinámicos adicionales que se agregan en tiempo de ejecución. Para proporcionar estos parámetros dinámicos, el proveedor de contenido de Windows PowerShell debe implementar el método System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* para controlar estos parámetros. Este método recupera los parámetros del elemento en la ruta de acceso indicada. Este método recupera parámetros dinámicos para el elemento en la ruta de acceso indicada y devuelve un objeto que tiene propiedades y campos con atributos de análisis similares a una clase de cmdlet o un objeto System.Management.Automation.RuntimeDefinedParameterDictionary. El entorno de ejecución de Windows PowerShell usa el objeto devuelto para agregar los parámetros al cmdlet .
Este proveedor de contenedores de Windows PowerShell no implementa este método. Sin embargo, el código siguiente es la implementación predeterminada de este método.
public object ClearContentDynamicParameters(string path)
{
return null;
}
public object ClearContentDynamicParameters(string path)
{
return null;
}
Ejemplo de código
Para obtener código de ejemplo completo, consulte ejemplo de código AccessDbProviderSample06.
Definición de tipos de objeto y formato
Al escribir un proveedor, puede ser necesario agregar miembros a objetos existentes o definir nuevos objetos. Una vez hecho esto, debe crear un archivo types que Windows PowerShell pueda usar para identificar los miembros del objeto y un archivo Format que defina cómo se muestra el objeto. Para obtener más información, vea extensión de tipos de objeto y formato.
Compilación del proveedor de Windows PowerShell
Consulte Registro de cmdlets, proveedores y aplicaciones host.
Probar el proveedor de Windows PowerShell
Cuando el proveedor de Windows PowerShell se haya registrado con Windows PowerShell, puede probarlo ejecutando los cmdlets admitidos en la línea de comandos. Por ejemplo, pruebe el proveedor de contenido de ejemplo.
Use el cmdlet Get-Content
para recuperar el contenido del elemento especificado en la tabla de base de datos en la ruta de acceso especificada por el parámetro Path
. El parámetro ReadCount
especifica el número de elementos para que el lector de contenido definido lea (valor predeterminado 1). Con la siguiente entrada de comando, el cmdlet recupera dos filas (elementos) de la tabla y muestra su contenido. Tenga en cuenta que la siguiente salida de ejemplo usa una base de datos ficticia de Access.
Get-Content -Path mydb:\Customers -ReadCount 2
ID : 1
FirstName : Eric
LastName : Gruber
Email : ericgruber@fabrikam.com
Title : President
Company : Fabrikam
WorkPhone : (425) 555-0100
Address : 4567 Main Street
City : Buffalo
State : NY
Zip : 98052
Country : USA
ID : 2
FirstName : Eva
LastName : Corets
Email : evacorets@cohowinery.com
Title : Sales Representative
Company : Coho Winery
WorkPhone : (360) 555-0100
Address : 8910 Main Street
City : Cabmerlot
State : WA
Zip : 98089
Country : USA
Véase también
creación de proveedores de Windows PowerShell
diseñar el proveedor de Windows PowerShell
extensión de tipos de objeto y formato
Implementar un proveedor de Windows PowerShell de navegación