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.
Este tema describe cómo crear un proveedor de PowerShell para Windows que permita al usuario manipular el contenido de los elementos en un almacén de datos. Como consecuencia, un proveedor que puede manipular el contenido de los elementos se denomina proveedor de contenido Windows PowerShell.
Nota:
Puedes descargar el archivo fuente (AccessDBSampleProvider06.cs) en C# de este proveedor utilizando el Microsoft Windows Software Development Kit para Windows Vista y los componentes de ejecución de .NET Framework 3.0. Para las instrucciones de descarga, consulta Cómo instalar Windows PowerShell y descargar el SDK de Windows PowerShell. Los archivos fuente descargados están disponibles en el <directorio de Ejemplos> de PowerShell. Para más información sobre otras implementaciones de proveedores de Windows PowerShell, consulte Diseñando su proveedor de PowerShell para Windows.
Defina la clase de proveedor de contenido PowerShell de Windows
Un proveedor de contenido PowerShell para Windows debe crear una clase .NET que soporte la interfaz System.Management.Automation.Provider.IContentCmdletProvider . Aquí está la definición de clase para el proveedor de ítems descrita en esta sección.
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : NavigationCmdletProvider, IContentCmdletProvider
Obsábanse 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 fácil de usar para el proveedor que utiliza Windows PowerShell. El segundo parámetro especifica las capacidades específicas de PowerShell de Windows que el proveedor expone al entorno de ejecución de Windows PowerShell durante el procesamiento de comandos. Para este proveedor, no hay capacidades específicas de Windows para PowerShell añadidas.
Definir funcionalidad de la clase base
Como se describe en Design Your Windows PowerShell Provider, la clase System.Management.Automation.Provider.NavigationCmdletProvider deriva de varias otras clases que ofrecían diferentes funcionalidades de proveedores. Por tanto, un proveedor de contenido de Windows PowerShell suele definir toda la funcionalidad proporcionada por esas clases.
Para más información sobre cómo implementar funcionalidades para añadir información de inicialización específica de la sesión y para liberar recursos que utiliza el proveedor, véase Creación de un proveedor básico de PowerShell para Windows. Sin embargo, la mayoría de los proveedores, incluido el que se describe aquí, pueden usar la implementación predeterminada de esta funcionalidad que ofrece 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 más información sobre cómo implementar estos métodos, consulte Creación de un proveedor de unidades PowerShell para Windows.
Para manipular los elementos de un almacén de datos, como obtener, configurar y compensar elementos, el proveedor debe implementar los métodos proporcionados por la clase base System.Management.Automation.Provider.ItemCmdletProvider . Para más información sobre cómo implementar estos métodos, consulte Creación de un proveedor de elementos para Windows PowerShell.
Para trabajar en almacenes de datos multicapa, el proveedor debe implementar los métodos proporcionados por la clase base System.Management.Automation.Provider.ContainerCmdletProvider . Para más información sobre cómo implementar estos métodos, consulte Creación de un proveedor de contenedores para Windows PowerShell.
Para soportar comandos recursivos, contenedores anidados y rutas relativas, el proveedor debe implementar la clase base System.Management.Automation.Provider.NavigationCmdletProvider . Además, este proveedor de contenido PowerShell de Windows puede adjuntar la interfaz System.Management.Automation.Provider.IContentCmdletProvider a la clase base System.Management.Automation.Provider.NavigationCmdletProvider , y por tanto debe implementar los métodos proporcionados por esa clase. Para más información, véase implementar esos métodos, véase Implementar un proveedor PowerShell de navegación para Windows.
Implementación de un lector de contenidos
Para leer contenido de un elemento, un proveedor debe implementar una clase lectora de contenido que derive de System.Management.Automation.Provider.IContentReader. El lector de contenido de este proveedor permite acceder al contenido de una fila en una tabla de datos. La clase 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 Dispos .
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
Implementando un redactor de contenidos
Para escribir contenido en un elemento, un proveedor debe implementar una clase de redactor de contenido derivada de System.Management.Automation.Provider.IContentWriter. La clase redactor de contenido define un método Write que escribe el contenido de la fila especificado, un método Seek que mueve al redactor de contenido, un método Close que cierra al redactor de contenido y un método Dispos .
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 soportar el Get-Content cmdlet. Este método devuelve el lector de contenido del elemento ubicado en la ruta especificada. El objeto lector puede abrirse para leer el contenido.
Aquí está la implementación de System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* para este método y 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 a recordar sobre la implementación de GetContentReader
Las siguientes condiciones 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 capacidades de proveedor de ExpandWildcards, Filtrar, Incluir o Excluir de la enumeración System.Management.Automation.Provider.ProviderCapabilities . En estos casos, la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* debe garantizar que la ruta pasada al método cumpla con los requisitos de las capacidades especificadas. Para ello, el método debe acceder a la propiedad adecuada, por ejemplo, las propiedades System.Management.Automation.Provider.CmdletProvider.Exclude* y System.Management.Automation.Provider.CmdletProvider.Include* .
Por defecto, las sobrescrituras de este método no deberían recuperar un lector para objetos ocultos al usuario a menos que la propiedad System.Management.Automation.Provider.CmdletProvider.Force* esté configurada en
true. Se debe escribir un error si la ruta representa un elemento oculto al usuario y System.Management.Automation.Provider.CmdletProvider.Force* está configurado comofalse.
Adjuntar parámetros dinámicos al Get-Content cmdlet
El Get-Content cmdlet 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 indicada y devuelve un objeto que tiene propiedades y campos con atributos de análisis similar a una clase cmdlet o un objeto System.Management.Automation.RuntimeDefinedParameterDictionary . El entorno de ejecución de Windows PowerShell utiliza el objeto devuelto para añadir los parámetros al cmdlet.
Este proveedor de contenedores de Windows PowerShell no implementa este método. Sin embargo, el siguiente código es la implementación predeterminada de este método.
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
Recuperando al redactor de contenidos
Para escribir contenido en un elemento, el proveedor debe implementar el System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* para soportar los Set-Content y Add-Content cmdlets. Este método devuelve al redactor de contenido del elemento ubicado en la ruta especificada.
Aquí está 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 a recordar sobre la implementación de GetContentWriter
Las siguientes condiciones pueden aplicarse a tu 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 capacidades de proveedor de ExpandWildcards, Filtrar, Incluir o Excluir de la enumeración System.Management.Automation.Provider.ProviderCapabilities . En estos casos, la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* debe garantizar que la ruta que se transmite al método cumpla con los requisitos de las capacidades especificadas. Para ello, el método debe acceder a la propiedad adecuada, por ejemplo, las propiedades System.Management.Automation.Provider.CmdletProvider.Exclude* y System.Management.Automation.Provider.CmdletProvider.Include* .
Por defecto, las sobrescrituras de este método no deberían recuperar un escritor para objetos ocultos al usuario a menos que la propiedad System.Management.Automation.Provider.CmdletProvider.Force* esté configurada en
true. Se debe escribir un error si la ruta representa un elemento oculto al usuario y System.Management.Automation.Provider.CmdletProvider.Force* está configurado comofalse.
Adjuntar parámetros dinámicos a los Add-Content y Set-Content Cmdlets
Los Add-Content cmdlets y Set-Content pueden requerir parámetros dinámicos adicionales que se añaden en tiempo de ejecución. Para proporcionar estos parámetros dinámicos, el proveedor de contenido PowerShell de Windows debe implementar el método System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* para gestionar estos parámetros. Este método recupera parámetros dinámicos para el elemento en la ruta indicada y devuelve un objeto que tiene propiedades y campos con atributos de análisis similar a una clase cmdlet o un objeto System.Management.Automation.RuntimeDefinedParameterDictionary . El entorno de ejecución de Windows PowerShell utiliza el objeto devuelto para añadir los parámetros a los cmdlets.
Este proveedor de contenedores de Windows PowerShell no implementa este método. Sin embargo, el siguiente código es la implementación predeterminada de este método.
public object GetContentWriterDynamicParameters(string path)
{
return null;
}
Eliminar contenido
Tu proveedor de contenido implementa el método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* en soporte del Clear-Content cmdlet. Este método elimina el contenido del elemento en la ruta especificada, pero deja el elemento intacto.
Aquí está 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 a recordar sobre la implementación de ClearContent
Las siguientes condiciones 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 capacidades de proveedor de ExpandWildcards, Filtrar, Incluir o Excluir de la enumeración System.Management.Automation.Provider.ProviderCapabilities . En estos casos, la implementación del método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* debe garantizar que la ruta que se le pasa al método cumpla con los requisitos de las capacidades especificadas. Para ello, el método debe acceder a la propiedad adecuada, por ejemplo, las propiedades System.Management.Automation.Provider.CmdletProvider.Exclude* y System.Management.Automation.Provider.CmdletProvider.Include* .
Por defecto, las sobrescrituras de este método no deberían borrar el contenido de objetos ocultos al usuario a menos que la propiedad System.Management.Automation.Provider.CmdletProvider.Force* esté configurada en
true. Se debe escribir un error si la ruta representa un elemento oculto al usuario y System.Management.Automation.Provider.CmdletProvider.Force* está configurado comofalse.Tu implementación del método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* debe llamar a System.Management.Automation.Provider.CmdletProvider.ShouldProcess y verificar su valor de retorno antes de realizar cualquier cambio en el almacén de datos. Este método se utiliza 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 a cambiar al usuario, mientras que el entorno de ejecución de Windows PowerShell gestiona cualquier configuración de línea de comandos o variable de preferencia para determinar qué debe mostrarse.
Tras la llamada a System.Management.Automation.Provider.CmdletProvider.ShouldProcess ,
trueel 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 retroalimentación que verifique si la operación debe continuar. La llamada a System.Management.Automation.Provider.CmdletProvider.ShouldContinue permite una comprobación adicional para posibles modificaciones peligrosas del sistema.
Adjuntar parámetros dinámicos al Clear-Content cmdlet
El Clear-Content cmdlet puede requerir parámetros dinámicos adicionales que se añaden en tiempo de ejecución. Para proporcionar estos parámetros dinámicos, el proveedor de contenido PowerShell de Windows debe implementar el método System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* para manejar estos parámetros. Este método recupera los parámetros del elemento en el camino indicado. Este método recupera parámetros dinámicos para el elemento en la ruta indicada y devuelve un objeto que tiene propiedades y campos con atributos de análisis similar a una clase cmdlet o un objeto System.Management.Automation.RuntimeDefinedParameterDictionary . El entorno de ejecución de Windows PowerShell utiliza el objeto devuelto para añadir los parámetros al cmdlet.
Este proveedor de contenedores de Windows PowerShell no implementa este método. Sin embargo, el siguiente código 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 ver el código de muestra completo, consulte AccessDbProviderSample06 Code Sample.
Definición de tipos de objetos y formato
Al escribir un proveedor, puede ser necesario añadir miembros a objetos existentes o definir nuevos objetos. Cuando esto se hace, debes 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 más información, véase Extensión de tipos de objetos y formato.
Construyendo el proveedor de PowerShell de Windows
Consulta cómo registrar cmdlets, proveedores y aplicaciones anfitrionas.
Probando el proveedor PowerShell de Windows
Cuando tu proveedor de PowerShell de Windows esté registrado en Windows PowerShell, puedes probarlo ejecutando los cmdlets compatibles en la línea de comandos. Por ejemplo, prueba el proveedor de contenido de muestra.
Utiliza el Get-Content cmdlet para recuperar el contenido del elemento especificado en la tabla de la base de datos en la ruta especificada por el Path parámetro. El ReadCount parámetro especifica el número de elementos que el lector de contenido definido debe leer (por defecto 1). Con la siguiente entrada de comando, el cmdlet recupera dos filas (elementos) de la tabla y muestra su contenido. Tenga en cuenta que el siguiente ejemplo de salida utiliza una base de datos Access ficticia.
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 PowerShell para Windows
Diseña tu proveedor PowerShell para Windows
Ampliación de los tipos de objetos y formato
Implementar un proveedor de PowerShell para Windows con navegación
Cómo registrar comandantes, proveedores y aplicaciones anfitrionas