PowerShell – Pratique : Les objets
L’un des grands atouts de PowerShell est que chaque commande ne renvoie pas du texte brut, mais des objets .NET complets. Comprendre ces objets est essentiel, car c’est ce qui rend possible le tri, le filtrage et la transformation des données dans le pipeline.
Explorer les objets avec Get-Member
La cmdlet Get-Member permet d’explorer les propriétés et méthodes des objets renvoyés par une commande.
Par exemple :
Get-Process | Get-Member
ou, en utilisant son alias :
Get-Process | gm
La première ligne indique le type d’objet (System.Diagnostics.Process). Ensuite, la sortie liste les propriétés (attributs comme Id, ProcessName, WorkingSet) et les méthodes (actions possibles sur l’objet).
La liste de priopriétés pour Get-Process est longue, et ne correspond pas tout à fait à ce que l’on voit dans la sortie de Get-Process, qui n’affiche que quelques colonnes.
PS C:\Users\Administrateur> Get-Process
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName
------- ------ ----- ----- ------ -- -- -----------
92 6 884 4660 0,02 3320 0 AggregatorHost
106 8 6292 10692 0,06 5256 1 conhost
...
Cela s’explique par le fait que PowerShell utilise une vue par défaut pour afficher les objets dans la console. Cette vue sélectionne certaines propriétés pertinentes pour un affichage concis.
Trier et sélectionner les données
Puisque nous travaillons avec des objets, il est facile de trier ou de réduire l’affichage à certaines propriétés.
Trier avec Sort-Object
Il est possible de trier les objets selon une ou plusieurs propriétés avec Sort-Object (alias sort).
Le paramètre -Property permet de spécifier la ou les propriétés à utiliser pour le tri. Le tri est par défaut en ordre croissant, mais on peut utiliser -Descending pour inverser l’ordre.
Par exemple, pour trier les processus par utilisation mémoire (WorkingSet) en ordre décroissant :
Get-Process | Sort-Object -Property WorkingSet -Descending
Il est possible de trier par plusieurs propriétés en les séparant par des virgules. Par exemple, pour trier d’abord par mémoire (VM), puis par ID (Id) en cas d’égalité :
Get-Process | Sort-Object VM, Id
Sélectionner avec Select-Object
Exemple : ne garder que certaines propriétés :
Get-Process | Select-Object Name, Id, CPU
Ici, seuls les noms, IDs et temps CPU des processus sont affichés.
La commande Select-Object contient également quelques paramètres utiles, comme -First et -Last pour ne garder que les premiers ou derniers objets :
Get-Process | Sort-Object -Property CPU -Descending | Select-Object -First 5 -Property Name
Dans cet exemple, on trie les processus par utilisation CPU, puis on ne garde que les 5 premiers, en affichant uniquement leur nom.
Remarquons que l'ordre des opérations est important. Ici, nous avons en premièrement fait le tri, puis la sélection. Cela nous a permis d'obtenir les 5 processus les plus gourmands en CPU. Si nous avions inversé l'ordre, soit en faisant la sélection des 5 premiers avant le tri, nous aurions simplement obtenu les 5 premiers processus dans l'ordre par défaut, sans considération de leur utilisation CPU. Et de ces 5 processus, nous aurions trié par CPU, ce qui n'aurait pas eu beaucoup de sens.
Pour aller plus loin : Les propriétés calculées
Il est possible de créer des propriétés personnalisées à la volée avec Select-Object. Par exemple, pour afficher le nom du processus et sa mémoire virtuelle en mégaoctets (Mo) :
Get-Process | Select-Object Name, @{Name="VM_Mo";Expression={$_.VM / 1MB -as [int]}}
Ici, nous avons créé une nouvelle propriété appelée VM_Mo (avec le paramètre Name) qui calcule la mémoire virtuelle en mégaoctets en divisant la propriété VM par 1MB. L’expression est définie avec le paramètre Expression, où $_ représente l’objet courant dans le pipeline. Nous utilisons également -as [int] pour convertir le résultat en entier, afin d’éviter les décimales.
La transformation dans le pipeline
Chaque commande dans le pipeline transforme les objets qu'elle reçoit en entrée. Par exemple, Get-Process génère des objets de type Process, Sort-Object prend ces objets et les réorganise, et Select-Object crée de nouveaux objets qui ne contiennent que les propriétés spécifiées.
Nous pouvons toujours vérifier le type des objets à chaque étape en insérant Get-Member dans le pipeline. Par exemple :
Get-Process | Sort-Object -Property CPU -Descending | Get-Member
Ici, le type d'objet reste System.Diagnostics.Process après le tri. En effet, Sort-Object ne modifie pas le type des objets, il les réorganise simplement.
Cependant, si nous ajoutons Select-Object, le type change :
Get-Process | Sort-Object -Property CPU -Descending | Select-Object -First 5 -Property Name | Get-Member
Le type d'objet devient Selected.System.Diagnostics.Process (on remarque le Selected. au début), indiquant que ce sont des objets sélectionnés avec seulement quelques propriétés.
Nous pouvons même vérifier le type que Get-Member renvoie :
Get-Process | Sort-Object -Property CPU -Descending | Select-Object -First 5 -Property Name | Get-Member | Get-Member
Ici, le type est System.Management.Automation.PSObject, qui est un type générique utilisé par PowerShell pour représenter des objets dynamiques. Nous voyons donc que même la sortie de Get-Member est un objet PowerShell, qui est un objet qui contient des informations sur les membres (propriétés et méthodes) de l'objet d'origine.
Filtrer les objets avec Where-Object
Where-Object permet de filtrer les objets selon une condition. Contrairement à Select-Object, qui choisit des propriétés spécifiques, Where-Object évalue une expression pour chaque objet et ne conserve que ceux qui satisfont la condition.
Par exemple, pour afficher uniquement les services qui sont en cours d’exécution :
Get-Service | Where-Object { $_.Status -eq "Running" }
Nous utilisons la notation $_ pour faire référence à l’objet courant dans le pipeline. L’expression { $_.Status -eq "Running" } est évaluée pour chaque objet, et seuls ceux qui retournent $true sont conservés. Les accolades {} délimitent le bloc de script qui contient l’expression. Elle est exécutée pour chaque objet passé dans le pipeline.
Comparer des données avec le pipeline
Nous pouvons comparer des ensembles d’objets en utilisant Compare-Object. Cela est utile pour détecter les différences entre deux listes, par exemple avant et après une modification du système, ou entre deux machines différentes.
Commençons par stocker la liste des processus dans une variable:
$procs1 = Get-Process
Ensuite, lançons une application (par exemple, notepad), puis récupérons à nouveau la liste des processus :
Start-Process notepad
$procs2 = Get-Process
Comparez les deux variables avec `Compare-Object`, en spécifiant la propriété `ProcessName` pour la comparaison :
```powershell
Compare-Object -ReferenceObject $procs1 -DifferenceObject $procs2 -Property ProcessName
Vous devriez voir apparaître notepad avec l’indicateur =>, ce qui signifie qu’il est apparu dans le deuxième ensemble.