Compartilhar via


Criando um Provedor de Contêineres Windows PowerShell

Este tópico descreve como criar um provedor de PowerShell para Windows que possa trabalhar em armazenamentos de dados multicamadas. Para esse tipo de repositório de dados, o nível superior do armazenamento contém os itens raiz e cada nível subsequente é referido como nó de itens filhos. Ao permitir que o usuário trabalhe nesses nós filhos, o usuário pode interagir hierarquicamente através do armazenamento de dados.

Provedores que podem trabalhar em repositórios de dados multinível são chamados de fornecedores de contêineres Windows PowerShell. No entanto, esteja ciente de que um provedor de contêineres Windows PowerShell só pode ser usado quando há um contêiner (sem contêineres aninhados) com itens nele. Se houver contêineres aninhados, então você deve implementar um provedor de navegação Windows PowerShell. Para mais informações sobre a implementação do provedor de navegação Windows PowerShell, veja Criação de um Provedor de Navegação Windows PowerShell.

Observação

Você pode baixar o arquivo de origem C# (AccessDBSampleProvider04.cs) desse provedor usando o Microsoft Windows Software Development Kit para Windows Vista e os Componentes de Runtime do .NET Framework 3.0. Para instruções de download, veja Como Instalar o Windows PowerShell e Baixar o Windows PowerShell SDK. Os arquivos fonte baixados estão disponíveis no <diretório PowerShell Samples> . Para mais informações sobre outras implementações de provedores Windows PowerShell, veja Designing Your Windows PowerShell Provider.

O provedor de contêineres Windows PowerShell descrito aqui define o banco de dados como seu único contêiner, com as tabelas e linhas do banco de dados definidas como itens do contêiner.

Cuidado

Esteja ciente de que esse design assume um banco de dados que possui um campo com o nome ID, e que o tipo do campo é LongInteger.

Definindo uma Classe de Provedor de Contêiner PowerShell para Windows

Um provedor de contêineres Windows PowerShell deve definir uma classe .NET que derive da classe base System.Management.Automation.Provider.ContainerCmdletProvider . Aqui está a definição de classe para o provedor de contêineres Windows PowerShell descrito nesta seção.

[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : ContainerCmdletProvider

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 provedor usado pelo Windows PowerShell. O segundo parâmetro especifica as capacidades específicas do Windows PowerShell que o provedor expõe ao tempo de execução do Windows PowerShell durante o processamento de comandos. Para esse provedor, não há capacidades específicas do PowerShell do Windows que sejam adicionadas.

Definindo a Funcionalidade Base

Como descrito em Designing Your Windows PowerShell Provider, a classe System.Management.Automation.Provider.ContainerCmdletProvider deriva de várias outras classes que forneciam funcionalidades diferentes de provedores. Portanto, um provedor de contêineres Windows PowerShell precisa definir toda a funcionalidade fornecida por essas classes.

Para implementar funcionalidades para adicionar informações de inicialização específicas de cada sessão e para liberar recursos usados pelo provedor, veja Criando um Provedor Básico de PowerShell para Windows. No entanto, a maioria dos provedores (incluindo o provedor descrito aqui) pode usar a implementação padrão dessa funcionalidade fornecida pelo Windows PowerShell.

Para obter acesso ao armazenamento de dados, o provedor deve implementar os métodos da classe base System.Management.Automation.Provider.DriveCmdletProvider . Para mais informações sobre como implementar esses métodos, veja Criando um Provedor de Unidades PowerShell para Windows.

Para manipular os itens de um armazenamento de dados, como obtenção, configuração e compensação de itens, o provedor deve implementar os métodos fornecidos pela classe base System.Management.Automation.Provider.ItemCmdletProvider . Para mais informações sobre como implementar esses métodos, veja Criando um Provedor de Itens do Windows PowerShell.

Recuperando Itens Crianças

Para recuperar um item filho, o provedor de contêineres do Windows PowerShell deve sobrescrever o método System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* para suportar chamadas do Get-ChildItem cmdlet. Esse método recupera itens filhos do armazenamento de dados e os grava no pipeline como objetos. Se o recurse parâmetro do cmdlet for especificado, o método recupera todos os filhos, independentemente do nível em que estejam. Se o recurse parâmetro não for especificado, o método recupera apenas um único nível de filhos.

Aqui está a implementação do método System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* para este provedor. Note que esse método recupera os itens filhos em todas as tabelas do banco de dados quando o caminho indica o banco de dados Access, e recupera os itens filhos das linhas dessa tabela se o caminho indicar uma tabela de dados.

protected override void GetChildItems(string path, bool recurse)
{
    // If path represented is a drive then the children in the path are 
    // tables. Hence all tables in the drive represented will have to be
    // returned
    if (PathIsDrive(path))
    {
        foreach (DatabaseTableInfo table in GetTables())
        {
            WriteItemObject(table, path, true);

            // if the specified item exists and recurse has been set then 
            // all child items within it have to be obtained as well
            if (ItemExists(path) && recurse)
            {
                GetChildItems(path + pathSeparator + table.Name, recurse);
            }
        } // foreach (DatabaseTableInfo...
    } // if (PathIsDrive...
    else
    {
        // Get the table name, row number and type of path from the
        // path specified
        string tableName;
        int rowNumber;

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

        if (type == PathType.Table)
        {
            // Obtain all the rows within the table
            foreach (DatabaseRowInfo row in GetRows(tableName))
            {
                WriteItemObject(row, path + pathSeparator + row.RowNumber,
                        false);
            } // foreach (DatabaseRowInfo...
        }
        else if (type == PathType.Row)
        {
            // In this case the user has directly specified a row, hence
            // just give that particular row
            DatabaseRowInfo row = GetRow(tableName, rowNumber);
            WriteItemObject(row, path + pathSeparator + row.RowNumber,
                        false);
        }
        else
        {
            // In this case, the path specified is not valid
            ThrowTerminatingInvalidPathException(path);
        }
    } // else
} // GetChildItems

Coisas para Lembrar Sobre a Implementação do GetChildItems

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*:

Anexando Parâmetros Dinâmicos ao Cmdlet Get-ChildItem

Às vezes, o Get-ChildItem cmdlet que chama System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems* requer parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer esses parâmetros dinâmicos, o fornecedor de contêineres do Windows PowerShell deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItemsDynamicParameters* . Esse método recupera parâmetros dinâmicos para o item no caminho indicado e retorna um objeto que possui 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 retornado para adicionar os parâmetros ao Get-ChildItem cmdlet.

Este provedor de contêineres Windows PowerShell não implementa esse método. No entanto, o código a seguir é a implementação padrão desse método.

Recuperando Nomes de Itens Filho

Para recuperar os nomes dos itens filhos, o provedor do contêiner PowerShell do Windows deve sobrescrever o método System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* para suportar chamadas do Get-ChildItem cmdlet quando seu Name parâmetro for especificado. Esse método recupera os nomes dos itens filhos para o caminho especificado ou nomes dos itens filhos para todos os contêineres, se o returnAllContainers parâmetro do cmdlet for especificado. Um nome de filho é a parte da folha de um caminho. Por exemplo, o nome filho do caminho C:\windows\system32\abc.dll é "abc.dll". O nome filho do diretório C:\windows\system32 é "system32".

Aqui está a implementação do método System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNames* para este provedor. Note que o método recupera nomes de tabelas se o caminho especificado indicar o banco de dados de acesso (drive) e números de linha se o caminho indicar uma tabela.

protected override void GetChildNames(string path,
                              ReturnContainers returnContainers)
{
    // If the path represented is a drive, then the child items are
    // tables. get the names of all the tables in the drive.
    if (PathIsDrive(path))
    {
        foreach (DatabaseTableInfo table in GetTables())
        {
            WriteItemObject(table.Name, path, true);
        } // foreach (DatabaseTableInfo...
    } // if (PathIsDrive...
    else
    {
        // Get type, table name and row number from path specified
        string tableName;
        int rowNumber;

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

        if (type == PathType.Table)
        {
            // Get all the rows in the table and then write out the 
            // row numbers.
            foreach (DatabaseRowInfo row in GetRows(tableName))
            {
                WriteItemObject(row.RowNumber, path, false);
            } // foreach (DatabaseRowInfo...
        }
        else if (type == PathType.Row)
        {
            // In this case the user has directly specified a row, hence
            // just give that particular row
            DatabaseRowInfo row = GetRow(tableName, rowNumber);

            WriteItemObject(row.RowNumber, path, false);
        }
        else
        {
            ThrowTerminatingInvalidPathException(path);
        }
    } // else
} // GetChildNames

Coisas para Lembrar Sobre a Implementação do GetChildNames

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.GetChildItems*:

Anexando parâmetros dinâmicos ao cmdlet de Get-ChildItem (nome)

Às vezes, o Get-ChildItem cmdlet (com o Name parâmetro) requer parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer esses parâmetros dinâmicos, o fornecedor de contêineres do Windows PowerShell deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.GetChildNamesDynamicParameters* . Esse método recupera os parâmetros dinâmicos do item no caminho indicado e retorna um objeto que possui 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 retornado para adicionar os parâmetros ao Get-ChildItem cmdlet.

Este provedor não implementa esse método. No entanto, o código a seguir é a implementação padrão desse método.

Renomeação dos Itens

Para renomear um item, um provedor de contêineres Windows PowerShell deve sobrescrever o método System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* para suportar chamadas do Rename-Item cmdlet. Esse método altera o nome do item no caminho especificado para o novo nome fornecido. O novo nome deve sempre ser relativo ao item pai (container).

Este provedor não sobrescreve o método System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem* . No entanto, a implementação padrão é a seguinte.

Coisas para Lembrar Sobre a Implementação do RenameItem

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.RenameItem*:

Anexando Parâmetros Dinâmicos ao Cmdlet Rename-Item

Às vezes, o Rename-Item cmdlet requer parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer esses parâmetros dinâmicos, o fornecedor de contêineres Windows PowerShell deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.RenameItemDynamicParameters* . Esse método recupera os parâmetros do item no caminho indicado e retorna um objeto que possui 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 retornado para adicionar os parâmetros ao Rename-Item cmdlet.

Este provedor de contêineres não implementa esse método. No entanto, o código a seguir é a implementação padrão desse método.

Criando Novos Itens

Para criar novos itens, um provedor de contêineres deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* para suportar chamadas do New-Item cmdlet. Esse método cria um item de dados localizado no caminho especificado. O type parâmetro do cmdlet contém o tipo definido pelo provedor para o novo item. Por exemplo, o provedor do Sistema de Arquivos usa um type parâmetro com o valor "file" ou "directory". O newItemValue parâmetro do cmdlet especifica um valor específico do provedor para o novo item.

Aqui está a implementação do método System.Management.Automation.Provider.ContainerCmdletProvider.NewItem* para esse provedor.

protected override void NewItem( string path, string type, object newItemValue )
{
    // Create the new item here after
    // performing necessary validations
    //
    // WriteItemObject(newItemValue, path, false);

    // Example
    //
    // if (ShouldProcess(path, "new item"))
    // {
    //      // Create a new item and then call WriteObject
    //      WriteObject(newItemValue, path, false);
    // }

} // NewItem
{
    case 1:
        {
            string name = pathChunks[0];

            if (TableNameIsValid(name))
            {
                tableName = name;
                retVal = PathType.Table;
            }
        }
        break;

    case 2:
        {
            string name = pathChunks[0];

Coisas para Lembrar Sobre a Implementação do NewItem

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*:

Anexando Parâmetros Dinâmicos ao Cmdlet New-Item

Às vezes, o New-Item cmdlet requer parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer esses parâmetros dinâmicos, o provedor do contêiner deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.NewItemDynamicParameters* . Esse método recupera os parâmetros do item no caminho indicado e retorna um objeto que possui 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 retornado para adicionar os parâmetros ao New-Item cmdlet.

Este provedor não implementa esse método. No entanto, o código a seguir é a implementação padrão desse método.

Remoção de Itens

Para remover itens, o provedor do Windows PowerShell deve sobrescrever o método System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem* para suportar chamadas do Remove-Item cmdlet. Esse método exclui um item do armazenamento de dados no caminho especificado. Se o recurse parâmetro do Remove-Item cmdlet for definido para true, o método remove todos os itens filhos, independentemente do nível deles. Se o parâmetro for definido para false, o método remove apenas um item no caminho especificado.

Este provedor não suporta remoção de itens. No entanto, o código a seguir é a implementação padrão de System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItem*.

Coisas para Lembrar Sobre a Implementação do RemoveItem

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.NewItem*:

Anexando Parâmetros Dinâmicos ao Cmdlet Remove-Item

Às vezes, o Remove-Item cmdlet requer parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer esses parâmetros dinâmicos, o provedor do contêiner deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters* para lidar com esses parâmetros. Esse método recupera os parâmetros dinâmicos do item no caminho indicado e retorna um objeto que possui 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 retornado para adicionar os parâmetros ao Remove-Item cmdlet.

Este provedor de contêineres não implementa esse método. No entanto, o código a seguir é a implementação padrão de System.Management.Automation.Provider.ContainerCmdletProvider.RemoveItemDynamicParameters*.

Consulta para Itens Filhos

Para verificar se os itens filhos existem no caminho especificado, o provedor de contêineres do Windows PowerShell deve sobrescrever o método System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* . Esse método retorna true se o item tiver filhos, e false caso contrário. Para um caminho nulo ou vazio, o método considera quaisquer itens no armazenamento de dados como filhos e retorna true.

Aqui está a substituição para o método System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems* . Se houver mais de duas partes de caminho criadas pelo método auxiliar ChunkPath, o método retorna false, já que apenas um contêiner de banco de dados e um contêiner de tabela são definidos. Para mais informações sobre esse método auxiliar, veja o método ChunkPath discutido em Criando um Provedor de Itens para Windows PowerShell.

protected override bool HasChildItems( string path )
{
    return false;
} // HasChildItems
        ErrorCategory.InvalidOperation, tableName));
}

return results;

Coisas para Lembrar Sobre a Implementação do HasChildItems

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.HasChildItems*:

Copiar Itens

Para copiar itens, o provedor de contêineres deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem para suportar chamadas do Copy-Item cmdlet. Esse método copia um item de dados da localização indicada pelo path parâmetro do cmdlet para a localização indicada pelo copyPath parâmetro. Se o recurse parâmetro for especificado, o método copia todos os subcontêineres. Se o parâmetro não for especificado, o método copia apenas um único nível de itens.

Este provedor não implementa esse método. No entanto, o código a seguir é a implementação padrão de System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem.

Coisas para Lembrar Sobre a Implementação do CopyItem

As seguintes condições podem se aplicar à sua implementação de System.Management.Automation.Provider.ContainerCmdletProvider.CopyItem:

Anexando Parâmetros Dinâmicos ao Cmdlet Copy-Item

Às vezes, o Copy-Item cmdlet requer parâmetros adicionais que são especificados dinamicamente em tempo de execução. Para fornecer esses parâmetros dinâmicos, o provedor de contêineres do Windows PowerShell deve implementar o método System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters* para lidar com esses parâmetros. Esse método recupera os parâmetros do item no caminho indicado e retorna um objeto que possui 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 retornado para adicionar os parâmetros ao Copy-Item cmdlet.

Este provedor não implementa esse método. No entanto, o código a seguir é a implementação padrão do System.Management.Automation.Provider.ContainerCmdletProvider.CopyItemDynamicParameters*.

Exemplo de código

Para um código de exemplo completo, veja AccessDbProviderSample04 Code Sample.

Construindo o Provedor Windows PowerShell

Veja como registrar cmdlets, provedores e aplicações host.

Testando o Provedor Windows PowerShell

Quando seu provedor de Windows PowerShell estiver registrado no Windows PowerShell, você pode testá-lo executando os cmdlets suportados na linha de comando. Esteja ciente de que o seguinte exemplo de saída utiliza um banco de dados fictício do Access.

  1. Execute o Get-ChildItem cmdlet para recuperar a lista de itens filhos de uma tabela Clientes no banco de dados Access.

    Get-ChildItem mydb:customers
    

    A seguinte saída aparece.

    PSPath        : AccessDB::customers
    PSDrive       : mydb
    PSProvider    : System.Management.Automation.ProviderInfo
    PSIsContainer : True
    Data          : System.Data.DataRow
    Name          : Customers
    RowCount      : 91
    Columns       :
    
  2. Execute o Get-ChildItem cmdlet novamente para recuperar os dados de uma tabela.

    (Get-ChildItem mydb:customers).Data
    

    A seguinte saída aparece.

    TABLE_CAT   : C:\PS\northwind
    TABLE_SCHEM :
    TABLE_NAME  : Customers
    TABLE_TYPE  : TABLE
    REMARKS     :
    
  3. Agora use o Get-Item cmdlet para recuperar os itens na linha 0 da tabela de dados.

    Get-Item mydb:\customers\0
    

    A seguinte saída aparece.

    PSPath        : AccessDB::customers\0
    PSDrive       : mydb
    PSProvider    : System.Management.Automation.ProviderInfo
    PSIsContainer : False
    Data          : System.Data.DataRow
    RowNumber     : 0
    
  4. Reutilize Get-Item para recuperar os dados dos itens na linha 0.

    (Get-Item mydb:\customers\0).Data
    

    A seguinte saída aparece.

    CustomerID   : 1234
    CompanyName  : Fabrikam
    ContactName  : Eric Gruber
    ContactTitle : President
    Address      : 4567 Main Street
    City         : Buffalo
    Region       : NY
    PostalCode   : 98052
    Country      : USA
    Phone        : (425) 555-0100
    Fax          : (425) 555-0101
    
  5. Agora use o New-Item cmdlet para adicionar uma linha a uma tabela existente. O Path parâmetro especifica o caminho completo até a linha e deve indicar um número de linha maior que o número existente de linhas na tabela. O Type parâmetro indica Row especificar o tipo de item a ser adicionado. Por fim, o Value parâmetro especifica uma lista delimitada por vírgulas de valores de coluna para a linha.

    New-Item -Path mydb:\Customers\3 -ItemType "Row" -Value "3,CustomerFirstName,CustomerLastName,CustomerEmailAddress,CustomerTitle,CustomerCompany,CustomerPhone, CustomerAddress,CustomerCity,CustomerState,CustomerZip,CustomerCountry"
    
  6. Verifique a correção da operação do novo item da seguinte forma.

    PS mydb:\> cd Customers
    PS mydb:\Customers> (Get-Item 3).Data
    

    A seguinte saída aparece.

    ID        : 3
    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
    

Consulte Também

Criando Provedores PowerShell para Windows

Projetando seu Provedor de PowerShell para Windows

Implementando um Item do Provedor Windows PowerShell

Implementando um Provedor de Navegação para Windows PowerShell

Como Registrar Comandantes, Provedores e Aplicações Host

Windows PowerShell SDK

Guia do Programador do Windows PowerShell