about_Pipelines

Mis à jour: mai 2014

S'applique à: Windows PowerShell 2.0, Windows PowerShell 3.0, Windows PowerShell 4.0, Windows PowerShell 5.0

RUBRIQUE

about_pipelines

DESCRIPTION COURTE

Combinaison de commandes en pipelines dans Windows PowerShell

DESCRIPTION DÉTAILLÉE

Un pipeline est une série de commandes reliées par des opérateurs de pipeline (|, code ASCII 124). Chaque opérateur de pipeline envoie les résultats de la commande précédente à la commande suivante.

Vous pouvez utiliser les pipelines pour envoyer les objets générés par une commande afin qu'ils soient utilisés comme entrée d'une autre commande pour traitement. Et vous pouvez encore envoyer la sortie de la commande à une autre commande. Le résultat est une chaîne de commandes très puissante ou « pipeline », composée d'une série de commandes simples.

Par exemple,

Command-1 | Command-2 | Command-3  

Dans cet exemple, les objets que Command-1 émet sont envoyés à Command-2. Command-2 traite les objets et les envoie à Command-3. Command-3 traite les objets et les envoie dans le pipeline. Comme il n'y a pas d'autres commandes dans le pipeline, les résultats sont affichés sur la console.

Dans un pipeline, les commandes sont traitées de gauche à droite, dans l'ordre dans lequel elles apparaissent. Le traitement est géré comme une seule opération et la sortie est affichée telle qu'elle est générée.

Voici un exemple simple. La commande suivante obtient le processus Notepad (Bloc-notes), puis l'arrête.

         get-process notepad | stop-process

La première commande utilise l'applet de commande Get-Process pour obtenir un objet représentant le processus Notepad. Elle utilise un opérateur de pipeline (|) pour envoyer l'objet processus à l'applet de commande Stop-Process, qui arrête le processus Notepad. Notez que la commande Stop-Process n'a pas de paramètre Name ou ID pour spécifier le processus, car le processus spécifié est envoyé à travers le pipeline.

Voici un exemple pratique. Ce pipeline de commande obtient les fichiers texte dans le répertoire en cours, sélectionne uniquement les fichiers longs de plus de 10 000 octets, les trie par longueur et affiche le nom et la longueur de chaque fichier dans une table.

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

Ce pipeline est composé de quatre commandes dans l'ordre spécifié. La commande est écrite horizontalement, mais nous allons montrer le processus verticalement dans le graphique suivant.

       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

UTILISATION DES PIPELINES

Les applets de commande Windows PowerShell ont été conçues pour être utilisées dans les pipelines. Par exemple, vous pouvez généralement diriger les résultats d'une applet de commande Get vers une applet de commande de type action (par exemple, une applet de commande Set, Start, Stop ou Rename) pour le même nom.

Par exemple, vous pouvez acheminer un service à partir de l'applet de commande Get-Service vers les applets de commande Start-Service ou Stop-Service (bien que les services désactivés ne puissent pas être redémarrés de cette façon).

Ce pipeline de commande démarre le service WMI sur l'ordinateur :

get-service wmi | start-service

Les applets de commande qui obtiennent et définissent les objets des fournisseurs Windows PowerShell, tels que les applets de commande Item et ItemProperty, sont également conçues pour être utilisées dans les pipelines.

Par exemple, vous pouvez diriger les résultats d'une commande Get-Item ou Get-ChildItem du fournisseur de Registre Windows PowerShell vers l'applet de commande New-ItemProperty. Cette commande ajoute une nouvelle entrée de Registre, NoOfEmployees, ayant la valeur 8124, à la clé de Registre MyCompany.

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

La plupart des applets de commande utilitaires, telles que Get-Member, Where-Object, Sort-Object, Group-Object et Measure-Object, sont utilisées presque uniquement dans les pipelines. Vous pouvez diriger tous les objets vers ces applets de commande.

Par exemple, vous pouvez diriger tous les processus de l'ordinateur vers la commande Sort-Object et les faire trier par nombre de handles dans le processus.

get-process | sort-object -property handles

En outre, vous pouvez acheminer des objets vers les applets de commande de mise en forme, telles que Format-List et Format-Table, les applets de commande Export, telles qu'Export-Clixml et Export-CSV, et les applets de commande Out, telles qu'Out-Printer.

Par exemple, vous pouvez diriger le processus Winlogon vers l'applet de commande Format-List pour afficher toutes les propriétés du processus dans une liste.

get-process winlogon | format-list -property *

Avec un peu de pratique, vous constaterez que la combinaison de commandes simples en pipelines permet de gagner du temps, d'économiser de la saisie et d'augmenter l'efficacité de votre script.

FONCTIONNEMENT DES PIPELINES

Lorsque vous « redirigez dans un pipeline » des objets, c'est-à-dire que vous envoyez les objets de la sortie d'une commande vers une autre commande, Windows PowerShell tente d'associer les objets redirigés avec l'un des paramètres de l'applet de commande de réception.

Pour ce faire, le composant de « liaison de paramètre » de Windows PowerShell, qui associe les objets d'entrée aux paramètres d'applet de commande, essaie de trouver un paramètre qui répond aux critères suivants :

-- Le paramètre doit accepter l'entrée d'un pipeline (tous ne le font pas)

-- Le paramètre doit accepter le type d'objet envoyé ou un type dans lequel l'objet peut être converti.

-- Le paramètre ne doit pas être déjà utilisé dans la commande.

Par exemple, l'applet de commande Start-Service possède de nombreux paramètres, mais seuls deux d'entre eux, Name et InputObject, acceptent l'entrée de pipeline. Le paramètre Name accepte les chaînes et le paramètre InputObject les objets de service. Par conséquent, vous pouvez rediriger des chaînes et des objets de service (et les objets avec les propriétés qui peuvent être converties en objets chaîne et service) vers Start-Service.

Si le composant de liaison de paramètre de Windows PowerShell ne peut pas associer les objets redirigés à un paramètre de l'applet de commande de réception, la commande échoue et Windows PowerShell vous invite à saisir les valeurs des paramètres manquants.

Vous ne pouvez pas obliger le composant de liaison de paramètre à associer les objets redirigés à un paramètre particulier ; vous ne pouvez même pas suggérer un paramètre. Au lieu de cela, la logique du composant gère le pipe aussi efficacement que possible.

TRAITEMENT UN À LA FOIS

Rediriger en pipe les objets vers une commande s'apparente beaucoup à l'utilisation d'un paramètre de la commande pour envoyer les objets.

Par exemple, la redirection en pipe d'objets représentant les services sur l'ordinateur vers une commande Format-Table, comme :

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

est similaire à l'enregistrement des objets de service dans une variable et à l'utilisation du paramètre InputObject de Format-Table pour envoyer l'objet de service.

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

ou à l'incorporation de la commande dans la valeur du paramètre

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

Cependant, il existe une différence importante. Lorsque vous redirigez en pipe plusieurs objets vers une commande, Windows PowerShell envoie les objets à la commande l'un après l'autre. Lorsque vous utilisez un paramètre de commande, les objets sont envoyés comme objet de tableau unique.

Cette différence apparemment technique peut avoir des conséquences intéressantes et, parfois, utiles.

Par exemple, si vous dirigez plusieurs objets de processus depuis l'applet de commande Get-Process vers l'applet de commande Get-Member, Windows PowerShell envoie chaque processus, un seul à la fois, à Get-Member. Get-Member affiche la classe .NET (type) des objets du processus, ainsi que leurs propriétés et méthodes. (Comme Get-Member élimine les doublons, si les objets sont tous du même type, un seul type d'objet est affiché.)

Dans ce cas, Get-Member affiche les propriétés et les méthodes de chaque objet de processus, autrement dit, un objet 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
                 ...

Toutefois, si vous utilisez le paramètre InputObject de Get-Member, Get-Member reçoit ensuite un tableau d'objets System.Diagnostics.Process comme seule unité et affiche les propriétés d'un tableau d'objets. (Notez le symbole de tableau ([]) après le nom de type 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()

Ce résultat peut ne pas être celui que vous attendiez, mais une fois que vous l'avez compris, vous pouvez l'utiliser. Par exemple, un tableau d'objets de processus possède une propriété Count que vous pouvez utiliser pour compter le nombre de processus sur l'ordinateur.

(get-process).count

Comme cette distinction peut être importante, n'oubliez pas que lorsque vous redirigez en pipe les objets vers une applet de commande, ils sont transmis l'un après l'autre.

ACCEPTE LES ENTRÉES DE PIPELINE

Pour recevoir des objets dans un pipeline, l'applet de commande de réception doit avoir un paramètre qui accepte les entrées de pipeline. Vous pouvez utiliser une commande Get-Help avec les paramètres Full ou Parameter afin de déterminer lequel des paramètres d'une applet de commande, le cas échéant, accepte les entrées de pipeline.

Dans l'affichage par défaut de Get-Help, l'élément « Accepte l'entrée de pipeline » apparaît dans le tableau des attributs de paramètre. Ce tableau s'affiche uniquement lorsque vous utilisez les paramètres Full ou Parameter de l'applet de commande Get-Help.

Par exemple, pour déterminer les paramètres dont l'applet de commande Start-Service accepte les entrées de pipeline, tapez :

        get-help start-service -full

        get-help start-service -parameter *

Par exemple, l'aide de l'applet de commande Start-Service indique que les paramètres Name et InputObject acceptent les entrées de pipeline (« true »). Tous les autres paramètres ont la valeur « false » dans la ligne « Accepter l'entrée de pipeline ? ».

        -name <string[]>
           Specifies the service names for the service to be started.
           The parameter name is optional. You can use "-Name" or its alias, 
           "-ServiceName", or you can omit the parameter name.

           Required?                    true
           Position?                    1
           Default value
      -->  Accept pipeline input?       true (ByValue, ByPropertyName)
           Accept wildcard characters?  true

        -inputObject <ServiceController[]>
           Specifies ServiceController objects representing the services to be started. Enter
           a variable that contains the objects or type a command or expression that gets the
           objects.

           Required?                    false
           Position?                    named
           Default value
      -->  Accept pipeline input?       true (ByValue)
           Accept wildcard characters?  false

Cela signifie que vous pouvez envoyer des objets (PsObjects) via le pipeline à l'applet de commande Where-Object et que Windows PowerShell associera l'objet au paramètre InputObject.

MÉTHODES D'ACCEPTATION D'UNE ENTRÉE DE PIPELINE

Les paramètres des applets de commande peuvent accepter les entrées de pipeline de deux façons différentes :

-- Par valeur : Les paramètres qui acceptent les entrées « par valeur » peuvent accepter les objets transmis dans le pipe qui ont le même type .NET que la valeur du paramètre ou les objets qui peuvent être convertis dans ce type.

Par exemple, le paramètre Name de Start-Service accepte les entrées de pipeline par valeur. Il peut accepter des objets de type chaîne (string) ou qui peuvent être convertis en chaînes.

-- Par nom de propriété : Les paramètres acceptant les entrées « par nom de propriété » peuvent accepter les objets redirigés en pipe uniquement lorsqu'une propriété de l'objet a le même nom que le paramètre.

Par exemple, le paramètre Name de Start-Service peut accepter des objets ayant une propriété Name.

(Pour afficher les propriétés d'un objet, dirigez-le vers Get-Member.)

Certains paramètres peuvent accepter des objets par valeur ou par nom de propriété. Ces paramètres sont conçus pour accepter facilement les entrées du pipeline.

RECHERCHE DES ERREURS DE PIPELINE

Si une commande échoue en raison d'une erreur de pipeline, vous pouvez étudier l'échec et écrire à nouveau la commande.

Par exemple, la commande suivante tente de déplacer une entrée de Registre depuis une clé de Registre vers une autre à l'aide de l'applet de commande Get-Item pour obtenir le chemin d'accès de destination, puis en dirigeant le chemin d'accès vers l'applet de commande Move-ItemProperty.

Plus particulièrement, la commande utilise l'applet de commande Get-Item pour obtenir le chemin d'accès de destination. Elle utilise un opérateur de pipeline (|) pour envoyer le résultat vers l’applet de commande Move-ItemProperty. La commande Move-ItemProperty spécifie le chemin d'accès actuel et le nom de l'entrée de Registre à déplacer.

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

La commande échoue et Windows PowerShell affiche le message d'erreur suivant :

         Move-ItemProperty : The input object cannot be bound to any parameters for the
         command either because the command does not take pipeline input or the input
         and its properties do not match any of the parameters that take pipeline input.
         At line:1 char:23
         + $a | move-itemproperty <<<<  -path hklm:\software\mycompany\design -name product

Pour enquêter, utilisez l'applet de commande Trace-Command afin de suivre le composant de liaison de paramètre de Windows PowerShell. La commande suivante suit le composant de liaison de paramètre pendant le traitement de la commande. Elle utilise le paramètre - pshost pour afficher les résultats sur la console et la commande - filepath pour les envoyer au fichier debug.txt à des fins de référence ultérieure.

         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

Les résultats du suivi sont longs, mais ils affichent les valeurs liées à l'applet de commande Get-Item, puis les valeurs nommées liées à l'applet de commande 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]
        ...

Enfin, l'applet de commande indique que la tentative de lier le chemin d'accès au paramètre Destination de Move-ItemProperty a échoué.

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

Pour analyser l'échec, utilisez l'applet de commande Get-Help afin d'afficher les attributs du paramètre Destination. La commande suivante obtient des informations détaillées sur le paramètre Destination.

get-help move-itemproperty -parameter destination

Les résultats montrent que Destination accepte les entrées de pipeline uniquement « par nom de propriété ». Autrement dit, l'objet redirigé doit avoir une propriété nommée Destination.

        -destination <string>
            Specifies the path to the destination location.

            Required?                    true
            Position?                    2
            Default value
            Accept pipeline input?       true (ByPropertyName)
            Accept wildcard characters?  true    

Pour afficher les propriétés de l'objet redirigé vers l'applet de commande Move-ItemProperty, redirigez-le vers l'applet de commande Get-Member. La commande suivante redirige les résultats de la première partie de la commande vers l'applet de commande Get-Member.

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

La sortie indique que l'élément est un objet Microsoft.Win32.RegistryKey qui n'a pas de propriété Destination. Telle est la raison pour laquelle la commande a échoué.

Pour corriger la commande, nous devons spécifier la destination dans l'applet de commande Move-ItemProperty. Nous pouvons utiliser une commande Get-ItemProperty pour obtenir le chemin d'accès, mais le nom et la destination doivent être spécifiés dans la partie Move-ItemProperty de la commande.

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

Pour vérifier que la commande a fonctionné, utilisez une commande Get-ItemProperty :

get-itemproperty hklm:\software\mycompany\sales

Les résultats montrent que l'entrée de Registre Product a été déplacée vers la clé 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

VOIR AUSSI

about_objects

about_parameters

about_command_syntax

about_foreach