Compartilhar via


about_Pipelines

TÓPICO
    about_pipelines

DESCRIÇÃO RESUMIDA
    Combinação de comandos em pipelines no Windows PowerShell 

DESCRIÇÃO LONGA
    Um pipeline é uma série de comandos conectada por operadores de 
    pipeline (|) (ASCII 124). Cada operador de pipeline envia os 
    resultados do comando anterior ao próximo comando.
     
    Você pode usar pipelines para enviar os objetos que são 
    produzidos por um comando para serem usados como entrada para 
    outro comando para processar. E ainda você pode enviar a saída 
    daquele comando para outro comando. O resultado é uma cadeia de 
    comando muito avançada ou "pipeline" que é composto por uma série 
    de comandos simples. 

    Por exemplo,  

    Command-1 | Command-2 | Command-3 

    Nesse exemplo, os objetos que Command-1 emite são enviados para 
    Command-2. Command-2 processa os objetos e os envia para 
    Command-3. Command-3 processa os objetos e os envia para o 
    pipeline. Como não há mais comandos no pipeline, os resultados 
    são exibidos no console.

    Em um pipeline, os comandos são processados da esquerda para a 
    direita na ordem que eles aparecem. O processamento é tratado 
    como uma única operação e a saída é exibida da forma que é gerada.

    Aqui está um exemplo simples. O comando a seguir obtém o processo 
    do Bloco de Notas e, em seguida, para-o.

         get-process notepad | stop-process

    O primeiro comando usa o cmdlet Get-Process para obter a um 
    objeto que representa o processo do Bloco de Notas. Ele usa um 
    operador de pipeline (|) para enviar o objeto de processo para o 
    cmdlet Stop-Process, que para o processo do Bloco de Notas. Note 
    que o comando Stop-Process não tem um parâmetro Name ou ID para 
    especificar o processo, porque o processo especificado é enviado 
    pelo pipeline.

    Aqui está um exemplo prático. Esse pipeline de comando obtém os 
    arquivos de texto no diretório atual, seleciona apenas os 
    arquivos que têm mais que 10.000 bytes, os classifica por 
    comprimento e exibe o nome e comprimento de cada arquivo em uma 
    tabela.

        Get-ChildItem -path *.txt | Where-Object {$_.length -gt 
        10000} | Sort-Object -property Length | Format-Table 
        -property name, length 

    Esse pipeline é composto por quatro comandos na ordem 
    especificada. O comando é escrito horizontalmente, mas 
    mostraremos o processo verticalmente no gráfico a seguir.

       Get-ChildItem -path *.txt

                  |
                  |  (FileInfo objects )
                  |  (    .txt         )
                  |
                  V                   

       Where-Object {$_.length -gt 10000}

                  |
                  |  (FileInfo objects )
                  |  (    .txt         )
                  |  ( Length > 10000  )
                  |
                  V

       Sort-Object -property Length

                  |
                  |  (FileInfo objects  )
                  |  (    .txt          )
                  |  ( Length > 10000   )
                  |  ( Sorted by length )
                  |
                  V

       Format-Table -property name, length

                  |  
                  |  (FileInfo objects     )
                  |  (    .txt             )
                  |  ( Length > 10000      )
                  |  ( Sorted by length    )
                  |  (Formatted in a table )
                  |
                  V
        Name                       Length
        ----                       ------
        tmp1.txt                    82920
        tmp2.txt                   114000
        tmp3.txt                   114000


USANDO PIPELINES

    Os cmdlets do Windows PowerShell foram criados para serem usados 
    em pipelines. Por exemplo, você pode enviar normalmente os 
    resultados de um cmdlet Get a um cmdlet de ação (como um cmdlet 
    Set, Start, Stop ou Rename) para o mesmo substantivo.

    Por exemplo, você pode enviar qualquer serviço do cmdlet 
    Get-Service para o cmdlet Start-Service ou Stop-Service (embora 
    serviços desabilitados não possam ser reiniciados desse modo).

    Esse pipeline de comando inicia o serviço WMI no computador:

    get-service wmi | start-service

    Os cmdlets que obtêm e definem objetos dos provedores do Windows 
    PowerShell, como os cmdlets Item e ItemProperty, também são 
    criados para serem usados em pipelines. 

    Por exemplo, você pode enviar os resultados de um comando 
    Get-Item ou Get-ChildItem no provedor de Registro do Windows 
    PowerShell para o cmdlet New-ItemProperty. Este comando adiciona 
    uma nova entrada do Registro, NoOfEmployees, com o valor de 8124, 
    à chave de Registro MyCompany.

       get-item -path HKLM:\Software\MyCompany | new-Itemproperty 
       -name NoOfEmployees -value 8124

    Muitos dos cmdlets de utilitário, como Get-Member, Where-Object, 
    Sort-Object, Group-Object e Measure-Object são usados quase 
    exclusivamente em pipelines. Você pode enviar qualquer objeto a 
    esses cmdlets.

    Por exemplo, você pode enviar todos os processos no computador 
    para o comando Sort-Object e tê-los classificado pelo número de 
    manipulações no processo.

    get-process | sort-object -property handles
    
    Além disso, você pode enviar qualquer objeto para os cmdlets de 
    formatação, como Format-List e Format-Table, os cmdlets de 
    exportação, como Export-Clixml e Export-CSV e os cmdlets de 
    saída, como Out-Printer.

    Por exemplo, você pode enviar o processo Winlogon ao cmdlet 
    Format-List para exibir todas as propriedades do processo em uma 
    lista.

    get-process winlogon | format-list -property *

    Com um pouco de prática, você verá que a combinação de comandos 
    simples em pipelines economiza tempo e digitação e torna seu 
    script mais eficiente.


COMO OS PIPELINES FUNCIONAM

     Quando você "envia" objetos aos objetos na saída de um comando 
     para outro comando, o Windows PowerShell tenta associar os 
     objetos enviados a um dos parâmetros do cmdlet de recebimento. 

     Para fazer isso, o componente "vinculação de parâmetro" do 
     Windows PowerShell, que associa objetos de entrada a parâmetros 
     de cmdlet, tenta localizar um parâmetro que atenda aos seguintes 
     critérios:
    
     -- O parâmetro deve aceitar entrada de um pipeline (não todos 
        aceitam)
     -- O parâmetro deve aceitar o tipo de objeto que é enviado ou um 
        tipo para o qual o objeto pode ser convertido.
     -- O parâmetro ainda não deve ser usado no comando.

     Por exemplo, o cmdlet Start-Service tem muitos parâmetros, mas 
     apenas dois deles, Name e InputObject, aceitam entrada do 
     pipeline. O parâmetro Name obtém cadeias de caracteres e o 
     parâmetro InputObject obtém objetos de serviço. Portanto, você 
     pode enviar cadeias de caracteres e objetos de serviço (e 
     objetos com propriedades que podem ser convertidas para cadeias 
     de caracteres e objetos de serviço) para Start-Service.

     Se o componente de vinculação de parâmetro do Windows PowerShell 
     não puder associar os objetos enviados a um parâmetro do cmdlet 
     de recebimento, o comando falhará e o Windows PowerShell 
     solicitará a você os valores de parâmetros não presentes.

     Você não pode forçar o componente de vinculação de parâmetro 
     para associar os objetos enviados com um parâmetro específico -- 
     você não pode nem mesmo sugerir um parâmetro. Em vez disso, a 
     lógica do componente gerencia o envio do modo mais eficiente 
     possível.


PROCESSAMENTO UM DE CADA VEZ

     O envio de objetos a um comando é como o uso de um parâmetro do 
     comando para enviar os objetos.

     Por exemplo, o envio de objetos que representam os serviços no 
     computador para um comando Format-Table, como:

          get-service | format-table -property name, 
          dependentservices

     É como salvar os objetos de serviço em uma variável e usar o 
     parâmetro InputObject de Format-Table para enviar o objeto de 
     serviço.

          $services = get-service
                  format-table -inputobject $services -property name, 
                  dependentservices

     ou fixar o comando no valor de parâmetro

                  format-table -inputobject (get-service wmi) 
                  -property name, dependentservices

     Contudo, há uma diferença importante. Quando você envia vários 
     objetos para um comando, o Windows PowerShell envia os objetos 
     ao comando um de cada vez. Quando você usa um parâmetro de 
     comando, os objetos são enviados como um único objeto de matriz.

     Essa diferença aparentemente técnica pode ter consequências 
     interessante e, às vezes, úteis.

     Por exemplo, se você enviar vários objetos de processo do cmdlet 
     Get-Process para o cmdlet Get-Member, o Windows PowerShell envia 
     cada objeto de processo, um de cada vez, ao Get-Member.
     Get-Member exibe a classe .NET (tipo) dos objetos de processo e 
     suas propriedades e métodos.
     (Get-Member elimina duplicatas; assim, se os objetos forem todos 
     do mesmo tipo, exibirá apenas um tipo de objeto.)

     Nesse caso, Get-Member exibe as propriedades e métodos de cada 
     objeto de processo, isto é, um objeto System.Diagnostics.Process.

                 get-process | get-member

                    TypeName: System.Diagnostics.Process


                 Name         MemberType     Definition
                 ----         ----------     ----------
                 Handles      AliasProperty  Handles = Handlecount
                 Name         AliasProperty  Name = ProcessName
                 NPM          AliasProperty  NPM = NonpagedSystemMemorySize
                 ...

      Contudo, se você usar o parâmetro InputObject de Get-Member, 
      Get-Member receberá uma matriz do objeto System.Diagnostics.Proc
      ess como uma única unidade e exibe as propriedades de uma 
      matriz de objetos. (Observe o símbolo de matriz ([]) depois que 
      o System.Object digitem nome.)


                get-member -inputobject (get-process)


                TypeName: System.Object[]

                Name        MemberType    Definition
                ----        ----------    ----------
                Count       AliasProperty Count = Length
                Address     Method        System.Object& Address(Int32 )
                Clone       Method        System.Object Clone()
                ...

     Esse resultado pode não ser o que você pretendia, mas depois de 
     entendê-lo, pode usá-lo. Por exemplo, uma matriz de objetos de 
     processo tem uma propriedade Count que você pode usar para 
     contar o número de processos no computador.

        (get-process).count
                
     Essa diferença pode ser importante, portanto, lembre-se de que, 
     quando você envia objetos a um cmdlet, eles são entregues um de 
     cada vez. 


ACEITA ENTRADA DO PIPELINE

    Para receber objetos em um pipeline, o cmdlet de recebimento deve 
    ter um parâmetro que aceite entrada do pipeline. Você pode usar 
    um comando Get-Help com os parâmetros Full ou Parameter para 
    determinar qual dos parâmetros de um cmdlet, se houver, aceita 
    entrada do pipeline.

    Na exibição padrão de Get-Help, o item "Aceita entrada do 
    pipeline" é exibido em uma tabela de atributos do parâmetro. Essa 
    tabela é exibida somente quando você usa os parâmetros Full ou 
    Parameter do cmdlet Get-Help.

    Por exemplo, para determinar qual dos parâmetros do cmdlet 
    Start-Service aceita entrada do pipeline, digite:
       
        get-help start-service -full

        get-help start-service -parameter *

    Por exemplo, a ajuda para o cmdlet Start-Service mostra que os 
    parâmetros Name e InputObject aceitam entrada do pipeline 
    ("true"). Todos os outros parâmetros têm um valor de "false" na 
    linha "Aceitar entrada do pipeline?".

        -name <string[]>
           Especifica os nomes para o serviço a ser iniciado.
           O nome do parâmetro é opcional. Você pode usar "-Name" ou 
           seu alias, "-ServiceName", ou omitir o nome do parâmetro.

           Necessário?                       true
           Posição?                          1
           Valor padrão
      -->  Aceitar entrada do pipeline?      true (ByValue, 
           ByPropertyName)
           Aceitar caracteres curinga?       true

        -inputObject <ServiceController[]>
           Especifica os objetos ServiceController que representam os 
           serviços que devem ser iniciados. Digite uma variável que 
           contenha os objetos ou digite um comando ou expressão que 
           obtenha os objetos.

           Necessário?                       false
           Posição?                          named
           Valor padrão
      --> Aceitar entrada do pipeline?       true (ByValue)
           Aceitar caracteres curinga?       false

     Isso significa que você pode enviar objetos (PsObjects) pelo 
     pipeline para o cmdlet Where-Object e o Windows PowerShell 
     associará o objeto ao parâmetro InputObject.


MÉTODOS DE ACEITAÇÃO DE ENTRADA DO PIPELINE

     Os parâmetros de cmdlets podem aceitar entrada do pipeline de um 
     destes dois modos:

     -- ByValue: os parâmetros que aceitam entrada "por valor" pode 
        aceitar objetos enviados que têm o mesmo tipo .NET como seu 
        valor de parâmetro ou objetos que podem ser convertidos 
        naquele tipo. 

        Por exemplo, o parâmetro Name de Start-Service aceita entrada 
        do pipeline por valor. Ele pode aceitar objetos de cadeia de 
        caracteres ou objetos que podem ser convertidos em cadeias de 
        caracteres.

     -- ByPropertyName: os parâmetros que aceitam entrada "por nome 
        de propriedade" podem aceitar objetos enviados somente quando 
        uma propriedade do objeto tiver o mesmo nome que o parâmetro.

        Por exemplo, o parâmetro Name de Start-Service pode aceitar 
        objetos que têm uma propriedade Name. 

        (Para listar as propriedades de um objeto, envie-o para 
        Get-Member.)

     Alguns parâmetros podem aceitar objetos por valor ou por nome de 
     propriedade. Esses parâmetros são criados para obter a entrada 
     do pipeline facilmente.


INVESTIGANDO ERROS DE PIPELINE

     Se um comando falhar por causa de um erro de pipeline, você 
     poderá investigar a falha e reescrever o comando.

     Por exemplo, o comando a seguir tenta mover uma entrada do 
     Registro de uma chave do Registro para outra usando o cmdlet 
     Get-Item para obter o caminho de destino e, em seguida, enviando 
     o caminho para o cmdlet Move-ItemProperty.

     De modo específico, o comando usa o cmdlet Get-Item para obter o 
     caminho de destino. Ele usa um operador de pipeline para enviar 
     o resultado para o cmdlet Move-ItemProperty. O comando 
     Move-ItemProperty especifica o caminho atual e nome da entrada 
     do Registro a ser movida. 

          get-item -path hklm:\software\mycompany\sales | 
          move-itemproperty -path hklm:\software\mycompany\design 
          -name product

     O comando falha e o Windows PowerShell exibe a seguinte mensagem 
     de erro:  

         Move-ItemProperty: o objeto de entrada não pode ser 
         associado a nenhum parâmetro para o comando porque o comando 
         não obtém a entrada do pipeline ou a entrada e suas 
         propriedades não correspondem a nenhum dos parâmetros que 
         obtêm entrada do pipeline.
         At line:1 char:23
         + $a | move-itemproperty <<<< -path 
         hklm:\software\mycompany\design -name product

    Para analisar, use o cmdlet Trace-Command para rastrear o 
    componente de vinculação de parâmetro do Windows PowerShell. O 
    comando a seguir rastreia o componente de vinculação de parâmetro 
    enquanto o comando está sendo processado. Ele usa o parâmetro 
    -pshost para exibir os resultados no console, e o comando 
    -filepath para enviá-los ao arquivo debug.txt para referência futura.

         trace-command -name parameterbinding -expression {get-item -path 
         hklm:\software\mycompany\sales | 
             move-itemproperty -path hklm:\software\mycompany\
             design -name product} -pshost -filepath debug.txt

    Os resultados do rastreamento são prolongados, mas eles mostram 
    os valores sendo vinculados ao cmdlet Get-Item e, em seguida, os 
    valores nomeados sendo vinculados ao cmdlet Move-ItemProperty. 

       ... 
        BIND NAMED cmd line args [Move-ItemProperty] 
            BIND arg  [hklm:\software\mycompany\design] to parameter [Path] 
       ...
            BIND arg [product] to parameter [Name] 
       ....
        BIND POSITIONAL cmd line args [Move-ItemProperty] 
       ...


    Finalmente, ele mostra que a tentativa de vincular o caminho ao 
    parâmetro Destination de Move-ItemProperty falhou.
        ...
        BIND PIPELINE object to parameters: [Move-ItemProperty] 
            PIPELINE object TYPE = [Microsoft.Win32.RegistryKey] 
            RESTORING pipeline parameter's original values Parameter 
            [Destination] PIPELINE INPUT ValueFromPipelineByPropertyName 
            NO COERCION Parameter [Credential] PIPELINE INPUT 
            ValueFromPipelineByPropertyName NO COERCION 
        ... 

     Para analisar a falha, use o cmdlet Get-Help para exibir os 
     atributos do parâmetro Destination. O comando a seguir obtém 
     informações detalhadas sobre o parâmetro Destination.

    get-help move-itemproperty -parameter destination

     Os resultados mostram que Destination obtém a entrada do 
     pipeline somente "por nome de propriedade".
     Isto é, o objeto enviado deve ter uma propriedade nomeada 
     Destination.

        -destination <string>
            Especifica o caminho até o local de destino.

            Necessário?                    true
            Posição?                       2
            Valor padrão
            Aceitar entrada do pipeline?   true (ByPropertyName) 
            Aceitar caracteres curinga?    true  

     Para ver as propriedades do objeto sendo enviado ao cmdlet 
     Move-ItemProperty, envie-o para o cmdlet Get-Member. O comando a 
     seguir envia os resultados da primeira parte do comando para o 
     cmdlet Get-Member.

          get-item -path hklm:\software\mycompany\sales | get-member
 
     A saída mostra que o item é um Microsoft.Win32.RegistryKey que 
     não tem uma propriedade Destination. Isso explica por que o 
     comando falhou.

     Para corrigir o comando, devemos especificar o destino no cmdlet 
     Move-ItemProperty. Podemos usar um comando Get-ItemProperty para 
     obter o caminho, mas o nome e o destino devem ser especificados 
     na parte Move-ItemProperty do comando.
          
         get-item -path hklm:\software\mycompany\design | 
             move-itemproperty -dest hklm:\software\mycompany\
             design -name product  

     Para verificar se o comando funcionou, use um comando 
     Get-ItemProperty:

    get-itemproperty hklm:\software\mycompany\sales

     Os resultados mostram que a entrada do Registro de Produto foi 
     movida a chave de Vendas.

        PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\
                       software\mycompany\sales 
        PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\
                       software\mycompany PSChildName : sales
        PSDrive      : HKLM
        PSProvider   : Microsoft.PowerShell.Core\Registry 
        Product      : 18

CONSULTE TAMBÉM
        about_objects
        about_parameters
        about_command_syntax
        about_foreach