RUBRIQUE about_pipelines DESCRIPTION COURTE Combinaison de commandes en pipelines dans Windows PowerShell DESCRIPTION LONGUE Un pipeline est une série de commandes connectées par des opérateurs de pipeline (|) (ASCII 124). Chaque opérateur de pipeline envoie les résultats de la commande précédente à la commande suivante. Vous pouvez utiliser des pipelines pour envoyer les objets générés par une commande à une autre commande qui les utilisera comme entrée à traiter. De même, vous pouvez envoyer la sortie de cette commande à une autre commande encore. Il en résulte une chaîne de commandes très puissante ou " pipeline " comprenant une série de commandes simples. Par exemple : Command-1 | Command-2 | Command-3 Dans cet exemple, les objets émis par Command-1 sont envoyés à Command-2. Command-2 les traite et les envoie à Command-3. Command-3 les traite et les envoie vers la suite du pipeline. Étant donné qu'il n'y a plus de commande dans le pipeline, les résultats s'affichent sur la console. Dans un pipeline, les commandes sont traitées de gauche à droite, dans l'ordre dans lequel elles apparaissent. Le traitement est mené comme une opération unique et la sortie est affichée dès 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. Remarquez que la commande Stop-Process ne comporte aucun 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 commandes obtient les fichiers texte du répertoire actif, sélectionne uniquement les fichiers de plus de 10 000 octets de long, les trie par longueur, puis 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 comporte quatre commandes dans l'ordre spécifié. La commande est écrite horizontalement, mais nous afficherons 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 DE PIPELINES Les applets de commande Windows PowerShell ont été conçues pour être utilisées dans des pipelines. Par exemple, vous pouvez généralement rediriger les résultats d'une applet de commande Get vers une applet de commande d'action (telle que Set, Start, Stop ou Rename) pour le même nom. Par exemple, vous pouvez rediriger tout service de l'applet de commande Get-Service vers l'applet de commande Start-Service ou Stop-Service (toutefois, les services désactivés ne peuvent pas être redémarrés de cette façon). Ce pipeline de commandes démarre le service WMI sur l'ordinateur local : get-service wmi | start-service Les applets de commande qui obtiennent et définissent des objets des fournisseurs Windows PowerShell, telles que les applets de commande Item et ItemProperty, sont également conçues pour être utilisées dans des pipelines. Par exemple, vous pouvez rediriger 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, avec la valeur 8124 à la clé de Registre MyCompany. get-item -path HKLM:\Software\MyCompany | new-Itemproperty -name NoOfEmployees -value 8124 Bon nombre des applets de commande utilitaires, telles que Get-Member, Where-Object, Sort-Object, Group-Object et Measure-Object sont utilisées presque exclusivement dans des pipelines. Vous pouvez rediriger tout type d'objet vers ces applets de commande. Par exemple, vous pouvez rediriger tous les processus de l'ordinateur vers la commande Sort-Object pour qu'ils soient triés selon le nombre de handles qu'ils contiennent. get-process | sort-object -property handles De même, vous pouvez rediriger tout type d'objet vers les applets de commande de mise en forme, telles que Format-List et Format-Table, les applets de commande Export, telles que Export-Clixml et Export-CSV, et les applets de commande Out, telles qu'Out-Printer. Par exemple, vous pouvez rediriger 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 vous apercevrez que le fait de combiner des commandes simples dans des pipelines est un réel gain de temps et rend l'écriture de scripts plus efficace. FONCTIONNEMENT DES PIPELINES Lorsque vous redirigez des objets, c'est-à-dire lorsque vous les envoyez de la sortie d'une commande vers une autre commande, Windows PowerShell essaie de les associer à l'un des paramètres de l'applet de commande destinataire. Pour cela, le composant de liaison des paramètres de Windows PowerShell, qui associe des objets d'entrée aux paramètres d'applet de commande, essaie de trouver un paramètre remplissant les critères suivants : -- Le paramètre doit accepter l'entrée provenant d'un pipeline (tous ne l'acceptent pas). -- Le paramètre doit accepter le type d'objet envoyé ou un type d'objet vers lequel l'objet peut être converti. -- Le paramètre ne doit pas déjà être utilisé dans la commande. Par exemple, l'applet de commande Start-Service comporte de nombreux paramètres, mais seuls deux d'entre eux, Name et InputObject, acceptent l'entrée du pipeline. Le paramètre Name accepte des chaînes et le paramètre InputObject accepte des objets services. Par conséquent, vous pouvez rediriger des chaînes et des objets services (ainsi que des objets avec des propriétés pouvant être converties en chaîne et objets services) vers Start-Service. Si le composant de liaison des paramètres de Windows PowerShell ne peut pas associer les objets redirigés à un paramètre de l'applet de commande destinataire, la commande échoue et Windows PowerShell vous invite à fournir les valeurs de paramètre manquantes. Vous ne pouvez pas forcer le composant de liaison des paramètres à associer des objets redirigés à un paramètre particulier. Vous ne pouvez même pas suggérer un paramètre. C'est en effet la logique du composant qui gère la redirection aussi efficacement que possible. TRAITEMENT INDIVIDUEL La redirection d'objets vers une commande est similaire à l'utilisation d'un paramètre de la commande pour l'envoi des objets. Par exemple, la redirection d'objets représentant les services de l'ordinateur vers une commande Format-Table, comme suit : get-service | format-table -property name, dependentservices est similaire à la procédure consistant à enregistrer des objets services dans une variable et à utiliser le paramètre InputObject de Format-Table pour les envoyer $services = get-service format-table -inputobject $services -property name, dependentservices ou à l'incorporation de la commande dans la valeur de paramètre. format-table -inputobject (get-service wmi) -property name, dependentservices Toutefois, il y a une différence importante. Lorsque vous redirigez plusieurs objets vers une commande, Windows PowerShell les envoie un par un. Lorsque vous utilisez un paramètre de commande, les objets sont envoyés comme un objet tableau unique. Cette différence apparemment technique peut avoir d'intéressantes, et parfois utiles, conséquences. Par exemple, si vous redirigez plusieurs objets processus de l'applet de commande Get-Process vers l'applet de commande Get-Member, Windows PowerShell envoie chaque objet processus, un par un, à Get-Member. Get-Member affiche la classe (type) .NET des objets processus et leurs propriétés et méthodes. (Get-Member supprime les doublons, donc si les objets sont tous du même type, il affiche un seul type d'objet.) Dans ce cas, Get-Member affiche les propriétés et méthodes de chaque objet 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 un tableau d'objets System.Diagnostics.Process comme seule unité et affiche les propriétés d'un tableau d'objets. (Remarquez 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 ce que vous attendiez, mais lorsque vous l'aurez compris, vous pourrez l'utiliser. Par exemple, un tableau d'objets processus comporte une propriété Count que vous pouvez utiliser pour compter le nombre de processus sur l'ordinateur. (get-process).count Cette distinction peut avoir son importance. Aussi, rappelez-vous que lorsque vous redirigez des objets vers une applet de commande, ils sont remis un par un. ACCEPTE L'ENTRÉE DE PIPELINE Pour recevoir des objets provenant d'un pipeline, l'applet de commande destinataire doit avoir un paramètre qui accepte l'entrée de pipeline. Vous pouvez utiliser une commande Get-Help avec les paramètres Full ou Parameter pour déterminer lequel, le cas échéant, des paramètres d'une applet de commande accepte l'entrée de pipeline. Dans l'affichage par défaut de Get-Help, l'élément "Accepts pipeline input" (" Accepte l'entrée de pipeline ") apparaît dans une table d'attributs de paramètre. Cette table s'affiche uniquement lorsque vous utilisez les paramètres Full ou Parameter de l'applet de commande Get-Help. Par exemple, pour déterminer lequel des paramètres de l'applet de commande Start-Service accepte l'entrée de pipeline, tapez : get-help start-service -full get-help start-service -parameter * Par exemple, l'aide sur l'applet de commande Start-Service indique que les paramètres Name et InputObject acceptent l'entrée de pipeline ("true", " vrai "). Tous les autres paramètres ont une valeur "false" (" faux ") pour la ligne "Accept pipeline input?" (" Accepter l'entrée de pipeline ? "). -name <string[]> Spécifie le nom de service du service à démarrer. Le nom de paramètre est facultatif. Vous pouvez utiliser " -Name " ou son alias, " -ServiceName ", ou encore omettre le nom de paramètre. Obligatoire ? true Position ? 1 Valeur par défaut --> Accepter l'entrée de pipeline ? true (ByValue, ByPropertyName) Accepter les caractères génériques ? true -inputObject <ServiceController[]> Spécifie les objets ServiceController représentant les services à démarrer. Entrez une variable contenant les objets ou tapez une commande ou une expression qui obtient les objets. Obligatoire ? false Position ? named Valeur par défaut --> Accepter l'entrée de pipeline ? true (ByValue) Accepter les caractères génériques ? false Cela signifie que vous pouvez envoyer des objets (PsObject) à travers le pipeline à l'applet de commande Where-Object et que Windows PowerShell associera l'objet au paramètre InputObject. MÉTHODES D'ACCEPTATION DE L'ENTRÉE DE PIPELINE Les paramètres d'applet de commande peuvent accepter l'entrée de pipeline de l'une des deux façons suivantes : -- Par valeur (ByValue) : les paramètres qui acceptent l'entrée " par valeur " peuvent accepter des objets redirigés qui ont le même type .NET que leur valeur de paramètre ou des objets pouvant être convertis en ce type. Par exemple, le paramètre Name de Start-Service accepte l'entrée de pipeline par valeur. Il peut accepter des objets chaînes ou des objets pouvant être convertis en chaînes. -- Par nom de propriété (ByPropertyName) : les paramètres qui acceptent l'entrée " par nom de propriété " peuvent accepter des objets redirigés uniquement lorsqu'une propriété de l'objet porte 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 répertorier les propriétés d'un objet, redirigez-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 l'entrée de pipeline. EXAMEN DES ERREURS DE PIPELINE Si une commande échoue à cause d'une erreur de pipeline, vous pouvez examiner cette dernière et la réécrire. Par exemple, la commande suivante essaie de déplacer une entrée du Registre d'une clé de Registre vers une autre en utilisant l'applet de commande Get-Item pour obtenir le chemin de destination, puis rediriger le chemin d'accès vers l'applet de commande Move-ItemProperty. La commande utilise, en particulier, l'applet de commande Get-Item pour obtenir le chemin de destination. Elle utilise un opérateur de pipeline pour envoyer le résultat à l'applet de commande Move-ItemProperty. La commande Move-ItemProperty spécifie le chemin d'accès actif et le nom de l'entrée du 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 : l'objet d'entrée ne peut être lié à aucun paramètre de la commande, soit parce que cette commande n'accepte pas l'entrée de pipeline, soit parce que l'entrée et ses propriétés ne correspondent à aucun des paramètres qui acceptent l'entrée de pipeline. À la ligne : 1 Caractère : 23 + $a | move-itemproperty <<<< -path hklm:\software\mycompany\design -name product Pour examiner la raison de l'échec, utilisez l'applet de commande Trace-Command pour tracer le composant de liaison des paramètres de Windows PowerShell. La commande suivante trace le composant de liaison des paramètres pendant que la commande procède au traitement. Elle utilise le paramètre -pshost pour afficher les résultats sur la console et la commande -filepath pour les envoyer vers le fichier debug.txt pour 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 de la trace sont longs, mais ils indiquent 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 [Chemin d'accès] ... BIND arg [produit] to parameter [Nom] .... BIND POSITIONAL cmd line args [Move-ItemProperty] ... Au final, cela montre que la tentative de liaison du 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 [Informations d'identification] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION ... Pour examiner la raison de l'échec, utilisez l'applet de commande Get-Help pour 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 indiquent que le paramètre Destination accepte uniquement l'entrée de pipeline " par nom de propriété ". Autrement dit, l'objet redirigé doit avoir une propriété nommée Destination. -destination <chaîne> Spécifie le chemin d'accès à l'emplacement de destination. Obligatoire ? true Position ? 2 Valeur par défaut Accepter l'entrée de pipeline ? true (ByPropertyName) Accepter les caractères génériques ? 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.Regi stryKey sans propriété Destination. Cela explique pourquoi la commande a échoué. Pour résoudre 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 indiquent que l'entrée du 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