TEMA
    about_pipelines

DESCRIPCIÓN BREVE
    Uso de canalizaciones para combinar comandos en Windows PowerShell 

DESCRIPCIÓN DETALLADA
    Una canalización es una serie de comandos conectados por 
    operadores de canalización (|) (ASCII 124). Cada operador de 
    canalización envía los resultados del comando anterior al 
    siguiente comando.
     
    Puede utilizar las canalizaciones para enviar los objetos 
    generados por un comando a otro comando para que los procese. Y 
    el resultado de ese comando lo puede enviar a un tercer comando. 
    El resultado es una cadena de comandos o "canalización" muy 
    eficaz que se compone de una serie de comandos sencillos. 

    Por ejemplo:  

	Command-1 | Command-2 | Command-3 

    En este ejemplo, los objetos que Command-1 emite se envían a 
    Command-2. Command-2 procesa los objetos y los envía a Command-3. 
    Command-3 procesa los objetos y los envía a través de la 
    canalización. Al no haber más comandos en la canalización, se 
    muestran los resultados en la consola.

    En una canalización, los comandos se procesan de izquierda a 
    derecha en el orden en que aparecen. El procesamiento se 
    administra como una sola operación y el resultado se muestra 
    cuando se genera.

    A continuación figura un ejemplo sencillo. El comando siguiente 
    obtiene el proceso Notepad (Bloc de notas) y, a continuación, lo 
    detiene.

         get-process notepad | stop-process

    El primer comando usa el cmdlet Get-Process para obtener el 
    objeto que representa el proceso Notepad. Utiliza un operador de 
    canalización (|) para enviar el objeto de proceso al cmdlet 
    Stop-Process, que detiene el proceso Notepad. Observe que el 
    comando Stop-Process no tiene parámetro Name ni ID para 
    especificar el proceso, ya que el proceso especificado se envía a 
    través de la canalización.

    A continuación figura un ejemplo práctico. Esta canalización de 
    comandos obtiene los archivos de texto del directorio actual, 
    selecciona únicamente los archivos de más de 10.000 bytes, los 
    ordena por tamaño y muestra el nombre y el tamaño de cada archivo 
    en una tabla.

        Get-ChildItem -path *.txt | Where-Object {$_.length -gt 10000} | 
        Sort-Object -property Length | Format-Table -property name, length 
    Esta canalización se compone de cuatro comandos en el orden 
    especificado. El comando se escribe horizontalmente, pero en el 
    siguiente gráfico se muestra el proceso verticalmente.

       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


USAR CANALIZACIONES

    Los cmdlets de Windows PowerShell se diseñaron para utilizarlos 
    en canalizaciones. Por ejemplo, normalmente se pueden canalizar 
    los resultados de un cmdlet Get a un cmdlet de acción (como un 
    cmdlet Set, Start, Stop o Rename) para el mismo sustantivo.

    Por ejemplo, se puede canalizar cualquier servicio del cmdlet 
    Get-Service al cmdlet Start-Service o Stop-Service (si bien los 
    servicios deshabilitados no se pueden reiniciar de esta manera).

    Esta canalización de comandos inicia el servicio WMI en el equipo:

	get-service wmi | start-service

    Los cmdlets que obtienen y establecen objetos de los proveedores 
    de Windows PowerShell, como los cmdlets Item e ItemProperty, 
    también se diseñaron para utilizarlos en canalizaciones. 

    Por ejemplo, se pueden canalizar los resultados de un comando 
    Get-Item o Get-ChildItem en el proveedor del Registro de Windows 
    PowerShell al cmdlet New-ItemProperty. Este comando agrega una 
    nueva entrada del Registro, NoOfEmployees, con el valor 8124, a 
    la clave del Registro MyCompany.

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

    Un gran número de los cmdlets de utilidad, como Get-Member, 
    Where-Object, Sort-Object, Group-Object y Measure-Object, se 
    utilizan casi exclusivamente en las canalizaciones. Se puede 
    canalizar cualquier objeto a estos cmdlets.

    Por ejemplo, se pueden canalizar todos los procesos del equipo al 
    comando Sort-Object para que se ordenen por el número de 
    identificadores en el proceso.

	get-process | sort-object -property handles
    
    Asimismo, se puede canalizar cualquier objeto a los cmdlets de 
    formato, como Format-List y Format-Table, a los cmdlets de 
    exportación, como Export-Clixml y Export-CSV, y a los cmdlets 
    Out, como Out-Printer.

    Por ejemplo, se puede canalizar el proceso Winlogon al cmdlet 
    Format-List para que se muestren todas las propiedades del 
    proceso en una lista.

	get-process winlogon | format-list -property *

    Con un poco de práctica, se dará cuenta de que al combinar 
    comandos en canalizaciones ahorrará tiempo y no tendrá que 
    escribir tanto, por lo que el uso de scripts resultará más eficaz.


FUNCIONAMIENTO DE LAS CANALIZACIONES

     Cuando se "canalizan" objetos, es decir, cuando se envían los 
     objetos del resultado de un comando a otro comando, Windows 
     PowerShell intenta asociar los objetos canalizados a uno de los 
     parámetros del cmdlet receptor. 

     Para ello, el componente de "enlace de parámetros" de Windows 
     PowerShell, que asocia los objetos de entrada con los parámetros 
     de los cmdlets, busca un parámetro que cumpla los siguientes 
     criterios:
    
     -- El parámetro debe aceptar entradas de canalizaciones (no 
        todos los parámetros las aceptan).
     -- El parámetro debe aceptar el tipo del objeto enviado o el 
        tipo en el que se puede convertir el objeto.
     -- El parámetro aún no puede estar presente en el comando.

     Por ejemplo, el cmdlet Start-Service tiene muchos parámetros, 
     pero solo dos de ellos, Name e InputObject, aceptan entradas de 
     canalizaciones. El parámetro Name toma cadenas y el parámetro 
     InputObject toma objetos de servicio. Por consiguiente, se 
     pueden canalizar cadenas y objetos de servicio (así como objetos 
     con propiedades que se pueden convertir en cadenas y objetos de 
     servicio) a Start-Service.

     Si el componente de enlace de parámetros de Windows PowerShell 
     no logra asociar los objetos canalizados con un parámetro del 
     cmdlet receptor, el comando generará un error y Windows 
     PowerShell solicitará los valores de parámetro que faltan.

     No se puede forzar dicho componente a que asocie los objetos 
     canalizados con un parámetro concreto; ni siquiera se puede 
     sugerir ningún parámetro. La lógica del componente administra la 
     canalización de la manera más eficaz posible.


PROCESAMIENTO DE UNO EN UNO

     La canalización de objetos a un comando es muy similar al uso de 
     un parámetro del comando para enviar los objetos.

     Por ejemplo, canalizar objetos que representan los servicios del 
     equipo a un comando Format-Table, como:

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

     es muy similar a guardar los objetos de servicio en una variable 
     y usar el parámetro InputObject de Format-Table para enviar el 
     objeto de servicio:

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

     o bien, incrustar el comando en el valor de parámetro:

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

     Sin embargo, hay una diferencia importante. Cuando se canalizan 
     varios objetos a un comando, Windows PowerShell los envía al 
     comando de uno en uno. Cuando se usa el parámetro de un comando, 
     los objetos se envían como un solo objeto de matriz.

     Esta diferencia aparentemente técnica puede tener consecuencias 
     interesantes y, a veces, útiles.

     Por ejemplo, si se canalizan varios objetos de proceso del 
     cmdlet Get-Process al cmdlet Get-Member, Windows PowerShell los 
     envía de uno en uno a Get-Member.
     Get-Member muestra la clase de .NET (tipo) de los objetos de 
     proceso así como sus propiedades y métodos.
     (Get-Member elimina los duplicados, por lo que solo muestra un 
     tipo de objeto si todos los objetos son del mismo tipo.)

     En este caso, Get-Member muestra las propiedades y los métodos 
     de cada objeto de proceso, es decir, un 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
                 ...

      Sin embargo, si se utiliza el parámetro InputObject de 
      Get-Member, Get-Member recibirá una matriz de objetos 
      System.Diagnostics.Process como una sola unidad y mostrará las 
      propiedades de una matriz de objetos. (Fíjese en el símbolo de 
      matriz ([]) después del nombre de tipo System.Object.)


                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()
                ...

     Puede que este resultado no sea lo que buscaba, pero si lo 
     comprende, podrá utilizarlo. Por ejemplo, una matriz de objetos 
     de proceso tiene una propiedad Count que se puede usar para 
     contar el número de procesos en el equipo.

		(get-process).count
                
     Esta distinción puede ser importante. Por lo tanto, cuando 
     canalice objetos a un cmdlet, no olvide que esos objetos se 
     envían de uno en uno. 


Acepta entradas de canalizaciones

    Para poder recibir objetos en una canalización, el cmdlet 
    receptor debe tener un parámetro que acepte las entradas de 
    canalizaciones. Se puede usar un comando Get-Help con los 
    parámetros Full o Parameter para determinar cuáles son los 
    parámetros de un cmdlet que aceptan entradas de canalizaciones, 
    en caso de que los haya.

    En la presentación predeterminada de Get-Help, el elemento 
    "Acepta entradas de canalizaciones" aparece en una tabla de 
    atributos de parámetro. Esta tabla se muestra únicamente si se 
    usa el parámetro Full o Parameter del cmdlet Get-Help.

    Por ejemplo, para determinar cuáles son los parámetros del cmdlet 
    Start-Service que aceptan entradas de canalizaciones, escriba:
       
        get-help start-service -full

        get-help start-service -parameter *

    Por ejemplo, en la Ayuda del cmdlet Start-Service se muestra que 
    los parámetros Name e InputObject aceptan entradas de 
    canalizaciones ("true"). Todos los demás parámetros tienen el 
    valor "false" en la fila "¿Acepta entradas de canalizaciones?".

        -name <string[]>
           Especifica el nombre de servicio del servicio que se va a iniciar.
           El nombre del parámetro es opcional. Puede usar "-Name" o su alias, 
           "-ServiceName", o puede omitir el nombre del parámetro.

           ¿Requerido?                    sí
           ¿Posición?                     1
           Valor predeterminado
      -->  ¿Aceptar canalización?         true (ByValue, ByPropertyName)
           ¿Aceptar caracteres comodín?   sí

        -inputObject <ServiceController[]>
           Especifica objetos ServiceController que representan los 
           servicios que se van a iniciar. Especifique una variable 
           que contenga los objetos o escriba un comando o una 
           expresión que obtenga los objetos.

           ¿Requerido?                    false
           ¿Posición?                     named
           Valor predeterminado
      -->  ¿Aceptar canalización?         true (ByValue)
           ¿Aceptar caracteres comodín?   false

     Esto significa que se pueden enviar objetos (PsObjects) a través 
     de la canalización al cmdlet Where-Object y Windows PowerShell 
     asociará el objeto al parámetro InputObject.


MÉTODOS PARA ACEPTAR ENTRADAS DE CANALIZACIONES

     Los parámetros de los cmdlets pueden aceptar las entradas de 
     canalizaciones de dos formas diferentes:

     -- ByValue: los parámetros que aceptan las entradas "por valor" 
        pueden aceptar objetos canalizados con el mismo tipo de .NET 
        que su valor de parámetro u objetos que se pueden convertir 
        en ese tipo. 

        Por ejemplo, el parámetro Name de Start-Service acepta 
        entradas de canalizaciones por valor. Puede aceptar objetos 
        de cadena u objetos que se pueden convertir en cadenas.

     -- ByPropertyName: los parámetros que aceptan entradas "por 
        nombre de propiedad" pueden aceptar objetos canalizados 
        únicamente si una propiedad del objeto tiene el mismo nombre 
        que el parámetro.

        Por ejemplo, el parámetro Name de Start-Service puede aceptar 
        objetos que tienen una propiedad Name. 

        (Para ver las propiedades de un objeto, canalícelo a Get-Member.)

     Algunos parámetros pueden aceptar objetos por valor o por nombre 
     de propiedad. Estos parámetros se han diseñado para que acepten 
     fácilmente las entradas de las canalizaciones.


INVESTIGAR LOS ERRORES DE CANALIZACIÓN

     Si un comando no se ejecuta correctamente debido a un error de 
     canalización, se puede investigar el error y rescribir el comando.

     Por ejemplo, el comando siguiente intenta mover una entrada del 
     Registro de una clave del Registro a otra usando el cmdlet 
     Get-Item a fin de obtener la ruta de acceso de destino y, a 
     continuación, canalizando la ruta de acceso al cmdlet 
     Move-ItemProperty.

     Concretamente, el comando utiliza el cmdlet Get-Item para 
     obtener la ruta de acceso de destino. Utiliza un operador de 
     canalización para enviar el resultado al cmdlet Move-ItemProperty. 
     El comando Move-ItemProperty especifica la ruta de acceso y el 
     nombre actuales de la entrada del Registro que se va a mover. 

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

     El comando genera un error y Windows PowerShell muestra el 
     siguiente mensaje de error:  

         Move-ItemProperty: El objeto de entrada no se puede enlazar 
         a ninguno de los parámetros del comando, bien porque el 
         comando no admite la entrada de canalización o porque la 
         entrada y sus propiedades no coinciden con ninguno de los 
         parámetros que aceptan entradas de canalización.
         En línea:1 carácter:23
         + $a | move-itemproperty <<<< -path hklm:\software\mycompany\design -name product

    Si desea investigar el error, utilice el cmdlet Trace-Command 
    para realizar un seguimiento del componente de enlace de 
    parámetros de Windows PowerShell. El comando siguiente realiza un 
    seguimiento del componente de enlace de parámetros durante el 
    procesamiento del comando. Usa el parámetro -pshost para mostrar 
    los resultados en la consola y utiliza el comando -filepath para 
    enviarlos al archivo debug.txt a fin de utilizarlos 
    posteriormente como referencia.

         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

    Los resultados del seguimiento son largos, pero muestran los 
    valores que se enlazan al cmdlet Get-Item y, a continuación, los 
    valores con nombre que se enlazan al 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] 
        ...


    Por último, muestra que se genera un error al intentar enlazar la 
    ruta de acceso al parámetro Destination de Move-ItemProperty.
        ...
        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 investigar el error, utilice el cmdlet Get-Help para ver 
     los atributos del parámetro Destination. El comando siguiente 
     obtiene información detallada sobre el parámetro Destination.

	get-help move-itemproperty -parameter destination

     Los resultados muestran que el parámetro Destination acepta las 
     entradas de canalización únicamente "por nombre de propiedad".
     Es decir, el objeto canalizado debe tener una propiedad 
     denominada Destination.

        -destination <string>
            Especifica la ruta de acceso a la ubicación de destino.

            ¿Requerido?                    sí
            ¿Posición?                     2 Valor predeterminado
            ¿Aceptar canalización?         true (ByPropertyName) 
            ¿Aceptar caracteres comodín?   sí  

     Para ver las propiedades del objeto que se canaliza al cmdlet 
     Move-ItemProperty, canalícelo al cmdlet Get-Member. El siguiente 
     comando canaliza los resultados de la primera parte del comando 
     al cmdlet Get-Member.

          get-item -path hklm:\software\mycompany\sales | get-member 

     El resultado muestra que el elemento es un objeto Microsoft.Win32
     .RegistryKey que no tiene la propiedad Destination. Esto explica 
     por qué el comando generó un error.

     Para corregir el comando, es preciso especificar el destino en 
     el cmdlet Move-ItemProperty. Se puede usar un comando 
     Get-ItemProperty para obtener la ruta de acceso, pero el nombre 
     y el destino deben especificarse en la parte Move-ItemProperty 
     del comando.
          
         get-item -path hklm:\software\mycompany\design | 
             move-itemproperty -dest hklm:\software\mycompany\design -name product  

     Para comprobar si el comando se ejecutó correctamente, utilice 
     un comando Get-ItemProperty:

	get-itemproperty hklm:\software\mycompany\sales

     Los resultados muestran que la entrada del Registro Product se 
     movió a la clave Sales.

        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

VEA TAMBIÉN
    Para obtener información acerca de los objetos, escriba el 
    siguiente comando en el símbolo del sistema de PowerShell:

        help about_objects

    Para obtener información acerca de los parámetros, escriba el siguiente comando:

        help about_parameters

    Para obtener información acerca de la sintaxis de comandos, escriba el siguiente comando:

        help about_command_syntax

    Para obtener información acerca de las instrucciones foreach, escriba el siguiente comando:

        help about_foreach




Tabla de contenido