PowerShell – Les objets

Introduction

Sous Unix, la plupart des commandes (comme ls, ps, etc.) produisent du texte brut. Pour manipuler ou filtrer ces résultats, on utilise souvent des outils comme grep, awk ou sed, qui traitent le texte ligne par ligne. Cela nécessite de connaître la structure exacte du texte et peut être fragile si le format de sortie change.

En PowerShell, chaque commande (cmdlet) retourne des objets structurés, pas du texte. Ces objets possèdent des propriétés et des méthodes accessibles directement. Par exemple, pour filtrer des processus, on peut utiliser Where-Object pour cibler une propriété précise, sans se soucier du format d'affichage.

Exemple Unix :

ps aux | grep notepad

Ici, on filtre les lignes contenant "notepad" dans la sortie texte de ps.

Exemple PowerShell :

Get-Process | Where-Object { $_.ProcessName -eq "notepad" }

Ici, on filtre les objets processus dont la propriété ProcessName vaut "notepad". Nous allons explorer plus en détail comment manipuler ces objets dans les sections suivantes.

PowerShell, un langage orienté objet

Pour quelqu'un qui vient de l'univers Unix, la notion d'objets en PowerShell peut sembler différente. En PowerShell, les objets sont au cœur de la manipulation des données. Contrairement à un simple texte, les objets contiennent des informations organisées en propriétés et méthodes, ce qui permet une manipulation plus riche et structurée des données. Vous verrez rapidement les avantages de cette approche!

PowerShell est construit sur le .NET Framework, ce qui signifie que toutes les données manipulées sont des objets .NET plutôt que du texte brut. Chaque objet possède :

  • Type : Définit la nature de l'objet (ex: System.Diagnostics.Process)
  • Propriétés : Attributs contenant des données (ex: ProcessName, Id)
  • Méthodes : Actions que l'objet peut effectuer (ex: Kill(), Start())

Avantages du modèle objet

  1. Structure préservée : Les données gardent leur organisation native
  2. Typage fort : Validation automatique des opérations
  3. Méthodes intégrées : Fonctionnalités directement disponibles sur les objets
  4. Intellisense : Autocomplétion basée sur le type d'objet

Types de données .NET courants

Sous PowerShell, les objects peuvent être de différents types. Nous retrouvons les types de base, comme les chaînes de caractères, les entiers, etc., mais aussi des types plus complexes comme les processus, les services, les fichiers, etc. qui sont spécifiques à l'environnement Windows.

Types système fondamentaux

  • System.String : Chaînes de caractères
  • System.Int32 : Entiers 32 bits
  • System.DateTime : Dates et heures
  • System.Boolean : Valeurs booléennes

Types spécialisés PowerShell

  • System.Diagnostics.Process : Processus système
  • System.ServiceProcess.ServiceController : Services Windows
  • System.IO.FileInfo : Informations de fichier
  • System.Management.ManagementObject : Objets WMI

Collections et tableaux

  • System.Array : Tableaux simples
  • System.Collections.ArrayList : Listes dynamiques
  • System.Collections.Hashtable : Tables de hachage

Introspection avec Get-Member

La cmdlet Get-Member illustre le concept de réflexion : la capacité d’un programme à examiner sa propre structure. Elle permet de découvrir dynamiquement les propriétés et les méthodes d’un objet et d’explorer interactivement ses types.

Par exemple, avec :

Get-Process | Get-Member

On découvre que les objets retournés sont de type System.Diagnostics.Process, avec des propriétés comme Id, ProcessName, et des méthodes comme Kill().

Comme tout objet en programmation, les objets PowerShell ont des propriétés (attributs) et des méthodes (fonctions). Get-Member liste ces membres, permettant de comprendre ce que l’on peut faire avec l’objet.

Anatomie de la sortie Get-Member

TypeName : System.Diagnostics.Process

Name                MemberType     Definition
----                ----------     ----------
ProcessName         Property       string ProcessName {get;}
Id                  Property       int Id {get;}
Kill               Method          void Kill()

La sortie de Get-Member est structurée en plusieurs colonnes :

  • Name : Nom de la propriété ou méthode
  • MemberType : Type de membre (Property, Method, etc.)
  • Definition : Signature détaillée

La colonne MemberType indique le type de chaque membre. Les types de membres sont classés en trois catégories, soit les propriétés, les méthodes et les événements.

Propriétés (Properties)

  • Property : Propriété simple en lecture/écriture
  • AliasProperty : Nom alternatif pour une propriété existante
  • ScriptProperty : Propriété calculée dynamiquement
  • NoteProperty : Propriété ajoutée à un objet existant

Méthodes (Methods)

  • Method : Fonction intégrée à l'objet
  • ScriptMethod : Méthode personnalisée ajoutée dynamiquement

Événements (Events)

  • Event : Notifications auxquelles on peut s'abonner

PowerShell étant un langage orienté objet, voici quelques rappels sur les objets en programmation :

  • Un objet est une instance d'une classe (type de données).
  • Une classe définit les propriétés (attributs) et méthodes (fonctions) associées à un type d'objet.
  • Les propriétés sont des variables attachées à un objet, tandis que les méthodes sont des fonctions qui opèrent sur l'objet.
  • Pour accéder à une propriété ou appeler une méthode, on utilise la syntaxe $objet.Propriété ou $objet.Méthode().

Tri des objets avec Sort-Object

Il est souvent utile de trier des objets en fonction de leurs propriétés. PowerShell fournit des cmdlets dédiées pour ces opérations.

Le tri en PowerShell est effectué avec Sort-Object, qui repose sur les comparateurs .NET. L’algorithme de tri est stable, ce qui signifie que l’ordre relatif des éléments égaux est conservé. De plus, il est possible de trier selon plusieurs critères, en évaluant les propriétés de gauche à droite.

Par exemple :

Sort-Object Property1, Property2, Property3

triera d’abord par Property1, puis par Property2 en cas d’égalité, et enfin par Property3.

Nous utilisons le pipeline pour enchaîner les commandes et trier la sortie d'une commande. Par exemple, pour trier les processus par nom puis par ID :

Get-Process | Sort-Object Name, Id

Plusieurs paramètres permettent de raffiner le tri : -Descending pour inverser l’ordre, -Unique pour supprimer les doublons, -CaseSensitive pour respecter la casse des chaînes, ou encore -Culture pour appliquer des règles de tri spécifiques à une langue.

Get-Process | Sort-Object CPU -Descending

Sélection des propriétés avec Select-Object

Une cmdlet peut retourner de nombreux objets avec plusieurs propriétés. Pour simplifier l’affichage ou réduire la quantité de données, on peut sélectionner uniquement certaines propriétés avec Select-Object.

La cmdlet Select-Object implémente ce que l’on appelle le pattern de projection. Elle permet de transformer un objet en un nouvel objet contenant seulement certaines propriétés choisies. Cette approche simplifie l’interface, réduit l’empreinte mémoire et expose uniquement les informations pertinentes.

Lorsqu’on applique une projection, l’objet d’origine, par exemple de type System.Diagnostics.Process, devient un objet de type Selected.System.Diagnostics.Process. Ce nouvel objet ne conserve que les propriétés sélectionnées, supprime les autres et reste fortement typé pour assurer la compatibilité avec d’autres opérations.

Select-Object offre plusieurs options pour affiner la sélection :

  • -First N : Sélectionne les N premiers objets
  • -Last N : Sélectionne les N derniers objets
  • -Skip N : Ignore les N premiers objets
  • -Unique : Supprime les doublons
  • -ExpandProperty : "Déplie" une propriété complexe

Par exemple, pour afficher uniquement les noms et IDs des processus :

Get-Process | Select-Object Name, Id

Pour sélectionner les 5 premiers processus triés par utilisation CPU :

Get-Process | Sort-Object CPU -Descending | Select-Object -First 5 Name

Ici, la sortie de Get-Process est triée par CPU, puis les 5 premiers objets sont projetés pour ne conserver que la propriété Name. La sortie finale est donc une liste de 5 noms de processus qui utilisent le plus de CPU.

Filtre des objets avec Where-Object

Il peut être nécessaire de filtrer des objets en fonction de critères spécifiques. La cmdlet Where-Object permet de réaliser cette tâche en évaluant une expression pour chaque objet et en ne conservant que ceux qui satisfont la condition.

Par exemple, pour obtenir uniquement les processus dont le nom est "notepad" :

Get-Process | Where-Object { $_.ProcessName -eq "notepad" }

Ici, le résultat de Get-Process est envoyé dans le pipeline, et Where-Object évalue l’expression { $_.ProcessName -eq "notepad" } pour chaque objet. Le symbole $_ représente l’objet courant dans le pipeline. L’expression { $_.ProcessName -eq "notepad" } est évaluée pour chaque objet, et seuls ceux qui retournent $true sont conservés dans la sortie.

Nous avons utilisé ici l’opérateur -eq pour la comparaison d’égalité. PowerShell propose une variété d’opérateurs de comparaison, notamment :

  • -ne : différent de
  • -lt : inférieur à
  • -le : inférieur ou égal à
  • -gt : supérieur à
  • -ge : supérieur ou égal à
  • -like : correspondance avec des jokers (*, ?)
  • -match : correspondance avec une expression régulière (regex)

Comparaison d’objets

Il peut être nécessaire de comparer des ensembles d’objets pour identifier les différences. La cmdlet Compare-Object permet de réaliser cette tâche en comparant deux collections d’objets.

La cmdlet Compare-Object illustre bien le fonctionnement d’algorithmes intégrés à PowerShell. Elle commence par tenter de comparer les objets complets. Si cela n’est pas possible, elle compare les propriétés spécifiées, et en dernier recours elle procède à une comparaison textuelle via la méthode ToString().

Dans ce contexte, il faut comprendre quelques termes clés. L’objet de référence (Reference Object) désigne l’ensemble de données servant de point de départ ou d’état initial. L’objet de différence (Difference Object) correspond à l’ensemble de données à comparer, qui représente un état final. La notion de propriété permet de préciser quelles caractéristiques spécifiques seront prises en compte lors de la comparaison.

$oldData = Get-Content "oldData.txt"
$newData = Get-Content "newData.txt"
Compare-Object -ReferenceObject $oldData -DifferenceObject $newData

Ici, nous avons créé deux variables $oldData et $newData contenant le contenu de deux fichiers texte. La cmdlet Compare-Object compare ces deux ensembles de données et affiche les différences. L'objet de référence est $oldData, tandis que l'objet de différence est $newData.

La cmdlet Get-Content lit le contenu des fichiers ligne par ligne, produisant ainsi des tableaux de chaînes de caractères. Chaque ligne est traitée comme un objet distinct, ce qui permet à Compare-Object d'identifier précisément les lignes ajoutées, supprimées ou modifiées entre les deux fichiers.

Lors de l’exécution, Compare-Object utilise des symboles particuliers : <= indique qu’un élément est présent uniquement dans l’objet de référence, => indique qu’un élément est présent uniquement dans l’objet de différence, et == montre que l’élément est présent dans les deux ensembles (lorsque le paramètre -IncludeEqual est utilisé).