Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este tópico descreve como criar um fornecedor Windows PowerShell que permita ao utilizador manipular o conteúdo dos itens num armazenamento de dados. Como consequência, um fornecedor que pode manipular o conteúdo dos itens é referido como fornecedor de conteúdo Windows PowerShell.
Observação
Pode descarregar o ficheiro-fonte C# (AccessDBSampleProvider06.cs) deste fornecedor usando o Microsoft Windows Software Development Kit para Windows Vista e Componentes de Runtime do .NET Framework 3.0. Para instruções de download, consulte Como Instalar o Windows PowerShell e Descarregar o Windows PowerShell SDK. Os ficheiros fonte descarregados estão disponíveis no <diretório PowerShell Samples> . Para mais informações sobre outras implementações de fornecedores Windows PowerShell, consulte Designing Your Windows PowerShell Provider.
Defina a Classe de Fornecedor de Conteúdo Windows PowerShell
Um fornecedor de conteúdo Windows PowerShell deve criar uma classe .NET que suporte a interface System.Management.Automation.Provider.IContentCmdletProvider . Aqui está a definição de classe para o fornecedor de itens descrita nesta secção.
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : NavigationCmdletProvider, IContentCmdletProvider
Note que, nesta definição de classe, o atributo System.Management.Automation.Provider.CmdletProviderAttribute inclui dois parâmetros. O primeiro parâmetro especifica um nome amigável para o fornecedor utilizado pelo Windows PowerShell. O segundo parâmetro especifica as capacidades específicas do Windows PowerShell que o fornecedor expõe ao tempo de execução do Windows PowerShell durante o processamento de comandos. Para este fornecedor, não existem capacidades específicas do Windows PowerShell adicionais.
Defina funcionalidade da classe base
Como descrito em Design Your Windows PowerShell Provider, a classe System.Management.Automation.Provider.NavigationCmdletProvider deriva de várias outras classes que forneciam funcionalidades diferentes do fornecedor. Um fornecedor de conteúdo Windows PowerShell, portanto, normalmente define toda a funcionalidade fornecida por essas classes.
Para mais informações sobre como implementar funcionalidades para adicionar informação de inicialização específica da sessão e para libertar recursos usados pelo fornecedor, consulte Criação de um Fornecedor Básico de PowerShell para Windows. No entanto, a maioria dos fornecedores, incluindo o fornecido aqui descrito, pode usar a implementação padrão desta funcionalidade fornecida pelo Windows PowerShell.
Para aceder ao armazenamento de dados, o fornecedor deve implementar os métodos da classe base System.Management.Automation.Provider.DriveCmdletProvider . Para mais informações sobre como implementar estes métodos, consulte Criar um Fornecedor de Unidades PowerShell para Windows.
Para manipular os itens de um armazenamento de dados, como obtenção, definição e compensação de itens, o fornecedor deve implementar os métodos fornecidos pela classe base System.Management.Automation.Provider.ItemCmdletProvider . Para mais informações sobre a implementação destes métodos, consulte Criação de um Fornecedor de Itens para Windows PowerShell.
Para trabalhar em armazenamentos de dados multicamada, o fornecedor deve implementar os métodos fornecidos pela classe base System.Management.Automation.Provider.ContainerCmdletProvider . Para mais informações sobre a implementação destes métodos, consulte Criar um Fornecedor de Contentores Windows PowerShell.
Para suportar comandos recursivos, contentores aninhados e caminhos relativos, o fornecedor deve implementar a classe base System.Management.Automation.Provider.NavigationCmdletProvider . Além disso, este fornecedor de conteúdo Windows PowerShell pode anexar a interface System.Management.Automation.Provider.IContentCmdletProvider à classe base System.Management.Automation.Provider.NavigationCmdletProvider , e deve, portanto, implementar os métodos fornecidos por essa classe. Para mais informações, veja implementar esses métodos, consulte Implementar um Fornecedor PowerShell para Navegação Windows.
Implementação de um Leitor de Conteúdos
Para ler conteúdo de um item, um fornecedor deve implementar uma classe de leitor de conteúdo que deriva de System.Management.Automation.Provider.IContentReader. O leitor de conteúdos deste fornecedor permite o acesso ao conteúdo de uma linha numa tabela de dados. A classe content reader define um método Read que recupera os dados da linha indicada e devolve uma lista que representa esses dados, um método Seek que move o leitor de conteúdo, um método Close que fecha o leitor de conteúdo e um 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
Implementação de um Redator de Conteúdos
Para escrever conteúdo para um item, um fornecedor deve implementar uma classe de escritor de conteúdos derivada de System.Management.Automation.Provider.IContentWriter. A classe de escritor de conteúdos define um método Write que escreve o conteúdo da linha especificada, um método Seek que move o escritor de conteúdos, um método Close que fecha o escritor de conteúdos e um 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
Recuperação do Leitor de Conteúdo
Para obter conteúdo de um item, o fornecedor deve implementar o System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* para suportar o Get-Content cmdlet. Este método devolve o leitor de conteúdo do item localizado no caminho especificado. O objeto leitor pode então ser aberto para ler o conteúdo.
Aqui está a implementação de System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* para este método para este fornecedor.
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
Coisas a Lembrar Sobre a Implementação do GetContentReader
As seguintes condições podem aplicar-se a uma implementação de System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader*:
Ao definir a classe de fornecedor, um fornecedor de conteúdo Windows PowerShell pode declarar capacidades de fornecedor de ExpandWildcards, Filtrar, Incluir ou Excluir, da enumeração System.Management.Automation.Provider.ProviderCapabilities . Nestes casos, a implementação do método System.Management.Automation.Provider.IContentCmdletProvider.GetContentReader* deve garantir que o caminho passado para o método cumpre os requisitos das capacidades especificadas. Para isso, o método deve aceder à propriedade apropriada, por exemplo, as propriedades System.Management.Automation.Provider.CmdletProvider.Exclude* e System.Management.Automation.Provider.CmdletProvider.Include* .
Por defeito, as sobreposições deste método não devem recuperar um leitor para objetos que estão ocultos ao utilizador, a menos que a propriedade System.Management.Automation.Provider.CmdletProvider.Force* esteja definida como
true. Deve ser escrito um erro se o caminho representar um item oculto ao utilizador e se System.Management.Automation.Provider.CmdletProvider.Force* estiver definido comofalse.
Anexação de Parâmetros Dinâmicos ao Cmdlet Get-Content
O Get-Content cmdlet pode exigir parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer estes parâmetros dinâmicos, o fornecedor de conteúdo Windows PowerShell deve implementar o método System.Management.Automation.Provider.IContentCmdletProvider.GetContentReaderdynamicparameters* . Este método recupera parâmetros dinâmicos para o item no caminho indicado e devolve um objeto com propriedades e campos com atributos de análise semelhantes a uma classe cmdlet ou a um objeto System.Management.Automation.RuntimeDefinedParameterDictionary . O runtime do Windows PowerShell usa o objeto devolvido para adicionar os parâmetros ao cmdlet.
Este fornecedor de contentores Windows PowerShell não implementa este método. No entanto, o código seguinte é a implementação padrão deste método.
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
public object GetContentReaderDynamicParameters(string path)
{
return null;
}
Recuperar o Redator de Conteúdos
Para escrever conteúdo num item, o fornecedor deve implementar o System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* para suportar os Set-Content cmdlets e Add-Content . Este método devolve o redator de conteúdo para o item localizado no caminho especificado.
Aqui está a implementação 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);
}
Coisas a Lembrar Sobre a Implementação do GetContentWriter
As seguintes condições podem aplicar-se à sua implementação de System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter*:
Ao definir a classe de fornecedor, um fornecedor de conteúdo Windows PowerShell pode declarar capacidades de fornecedor de ExpandWildcards, Filtrar, Incluir ou Excluir, da enumeração System.Management.Automation.Provider.ProviderCapabilities . Nestes casos, a implementação do método System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriter* deve garantir que o caminho passado para o método cumpre os requisitos das capacidades especificadas. Para isso, o método deve aceder à propriedade apropriada, por exemplo, as propriedades System.Management.Automation.Provider.CmdletProvider.Exclude* e System.Management.Automation.Provider.CmdletProvider.Include* .
Por defeito, as sobrescrituras deste método não devem recuperar um escritor para objetos que estão ocultos ao utilizador, a menos que a propriedade System.Management.Automation.Provider.CmdletProvider.Force* esteja definida para
true. Deve ser escrito um erro se o caminho representar um item oculto ao utilizador e se System.Management.Automation.Provider.CmdletProvider.Force* estiver definido comofalse.
Anexação de Parâmetros Dinâmicos aos Cmdlets Add-Content e Set-Content
Os Add-Content cmdlets e Set-Content podem exigir parâmetros dinâmicos adicionais que são adicionados a um runtime. Para fornecer estes parâmetros dinâmicos, o fornecedor de conteúdo PowerShell do Windows deve implementar o método System.Management.Automation.Provider.IContentCmdletProvider.GetContentWriterDynamicParameters* para lidar com estes parâmetros. Este método recupera parâmetros dinâmicos para o item no caminho indicado e devolve um objeto com propriedades e campos com atributos de análise semelhantes a uma classe cmdlet ou a um objeto System.Management.Automation.RuntimeDefinedParameterDictionary . O runtime do Windows PowerShell usa o objeto devolvido para adicionar os parâmetros aos cmdlets.
Este fornecedor de contentores Windows PowerShell não implementa este método. No entanto, o código seguinte é a implementação padrão deste método.
public object GetContentWriterDynamicParameters(string path)
{
return null;
}
Limpar conteúdo
O seu fornecedor de conteúdos implementa o método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* em suporte ao Clear-Content cmdlet. Este método remove o conteúdo do item no caminho especificado, mas mantém o item intacto.
Aqui está a implementação do método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* para este fornecedor.
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
Coisas a Lembrar Sobre a Implementação do ClearContent
As seguintes condições podem aplicar-se a uma implementação de System.Management.Automation.Provider.IContentCmdletProvider.ClearContent*:
Ao definir a classe de fornecedor, um fornecedor de conteúdo Windows PowerShell pode declarar capacidades de fornecedor de ExpandWildcards, Filtrar, Incluir ou Excluir, da enumeração System.Management.Automation.Provider.ProviderCapabilities . Nestes casos, a implementação do método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* deve garantir que o caminho passado para o método cumpre os requisitos das capacidades especificadas. Para isso, o método deve aceder à propriedade apropriada, por exemplo, as propriedades System.Management.Automation.Provider.CmdletProvider.Exclude* e System.Management.Automation.Provider.CmdletProvider.Include* .
Por defeito, as sobrescrituras deste método não devem limpar o conteúdo dos objetos ocultos ao utilizador, a menos que a propriedade System.Management.Automation.Provider.CmdletProvider.Force* esteja definida para
true. Deve ser escrito um erro se o caminho representar um item oculto ao utilizador e se System.Management.Automation.Provider.CmdletProvider.Force* estiver definido comofalse.A sua implementação do método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* deve chamar System.Management.Automation.Provider.CmdletProvider.ShouldProcess e verificar o seu valor de retorno antes de fazer quaisquer alterações ao armazenamento de dados. Este método é usado para confirmar a execução de uma operação quando é feita uma alteração ao armazenamento de dados, como limpar conteúdo. O método System.Management.Automation.Provider.CmdletProvider.ShouldProcess envia o nome do recurso a ser alterado para o utilizador, com o runtime do Windows PowerShell a tratar de quaisquer definições de linha de comandos ou variáveis de preferência para determinar o que deve ser exibido.
Após a chamada para System.Management.Automation.Provider.CmdletProvider.ShouldProcess retorna
true, o método System.Management.Automation.Provider.IContentCmdletProvider.ClearContent* deve chamar o método System.Management.Automation.Provider.CmdletProvider.ShouldContinue . Este método envia uma mensagem ao utilizador para permitir feedback e verificar se a operação deve continuar. A chamada para System.Management.Automation.Provider.CmdletProvider.ShouldContinue permite uma verificação adicional para modificações potencialmente perigosas do sistema.
Anexação de Parâmetros Dinâmicos ao Cmdlet Clear-Content
O Clear-Content cmdlet pode exigir parâmetros dinâmicos adicionais que são adicionados em tempo de execução. Para fornecer estes parâmetros dinâmicos, o fornecedor de conteúdo Windows PowerShell deve implementar o método System.Management.Automation.Provider.IContentCmdletProvider.ClearContentDynamicParameters* para lidar com estes parâmetros. Este método recupera os parâmetros do item no caminho indicado. Este método recupera parâmetros dinâmicos para o item no caminho indicado e devolve um objeto com propriedades e campos com atributos de análise semelhantes a uma classe cmdlet ou a um objeto System.Management.Automation.RuntimeDefinedParameterDictionary . O runtime do Windows PowerShell usa o objeto devolvido para adicionar os parâmetros ao cmdlet.
Este fornecedor de contentores Windows PowerShell não implementa este método. No entanto, o código seguinte é a implementação padrão deste método.
public object ClearContentDynamicParameters(string path)
{
return null;
}
public object ClearContentDynamicParameters(string path)
{
return null;
}
Exemplo de código
Para código de exemplo completo, consulte AccessDbProviderSample06 Code Sample.
Definição dos Tipos de Objetos e Formatação
Ao escrever um fornecedor, pode ser necessário adicionar membros a objetos existentes ou definir novos objetos. Quando isto estiver feito, deve criar um ficheiro Types que o Windows PowerShell possa usar para identificar os membros do objeto e um ficheiro Format que defina como o objeto é exibido. Para mais informações, veja Extensão dos Tipos de Objetos e Formatação.
Construir o Fornecedor Windows PowerShell
Veja Como Registar Cmdlets, Fornecedores e Aplicações Anfitriãs.
Testar o Fornecedor Windows PowerShell
Quando o seu fornecedor de PowerShell para Windows estiver registado no Windows PowerShell, pode testá-lo executando os cmdlets suportados na linha de comandos. Por exemplo, teste o fornecedor de conteúdo de exemplo.
Use o Get-Content cmdlet para recuperar o conteúdo do item especificado na tabela da base de dados no caminho especificado pelo Path parâmetro. O ReadCount parâmetro especifica o número de itens que o leitor de conteúdo definido deve ler (padrão 1). Com a entrada seguinte do comando, o cmdlet recupera duas linhas (itens) da tabela e apresenta o seu conteúdo. Note que o seguinte exemplo de saída utiliza uma base de dados Access fictícia.
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
Ver também
Criação de fornecedores PowerShell para Windows
Projete o seu fornecedor PowerShell para Windows
Extensão dos Tipos de Objetos e Formatação
Implementar um fornecedor PowerShell de navegação para Windows