Windows PowerShell Filtrage et formatage de données

Don Jones

Il ne fait pas de doute que Windows PowerShell peur retourner un grand nombre d'informations intéressantes, et ce sans trop d'efforts de votre part. Par exemple, considérez le simple cmdlet Get-WMIObject, qui peut être utilisé pour retourner une liste de services sur l'ordinateur local. L'affichage par défaut, qui liste l'état, le nom et le mode de démarrage des

services s'exécutant, est essentiellement un affichage de lignes de commande de la console de Services. Windows PowerShell™ vous permet d'y accéder plus facilement.

Mais il existe beaucoup plus d'informations disponibles pour les services que celles qui sont indiquées dans l'affichage par défaut. Essayez cette commande :

$s = get-wmiobject win32_service
$s[0] | gm

La première ligne de la commande retourne une collection de tous les services (ou, plus précisément, de toutes les instances de la classe Win32_Service de WMI classe de Windows® Management Instrumentation, ou WMI), et les enregistrent dans la variable $s. La deuxième ligne prend le premier service dans cette collection (le zéro de numéro ordinal, indiqué dans les crochets) et le transmet au cmdlet Get-Member, que j'ai abrégé en utilisant son alias, gm. Le résultat affiche toutes les propriétés et les méthodes disponibles pour ce type de données. J'ai décidé d'utiliser la classe Win32_Service dans WMI, au lieu du cmdlet Get-Service intégré à Windows PowerShell, parce que WMI révèle en fait plus d'informations que l'objet Service-Controller de Microsoft®.NET, y compris la propriété Start­Name. Cette propriété m'indique le nom du compte utilisateur sous lequel le service est exécuté. Vous pouvez vérifier le nom d'une instance unique, telle que la première, comme suit :

PS C:\> $s[0].StartName
LocalSystem

Cependant, il n'est pas très utile de se référer aux services par leur ordinal dans la collection, puisque les services n'apparaissent pas dans un ordre particulier. (Ils sont d'habitude listés par ordre alphabétique, mais pas toujours.) Du point de vue de la gestion, vous serez probablement plus intéressé par une liste de tous services, ainsi que le compte que chaque service utilise pour se connecter. Ce serait pratique pour un audit de conformité, par exemple. Donc faisons une pause pour regarder ce que WMI propose par défaut. J'utiliserai l'alias de Get-WMIObject, gwmi (voir la figure 1).

Figure 1 Utilisation de gwmi

PS C:\> gwmi win32_service

ExitCode  : 0
Name      : AcrSch2Svc
ProcessId : 1712
StartMode : Auto
State     : Running
Status    : OK

ExitCode  : 1077
Name      : Adobe LM Service
ProcessId : 0
StartMode : Manual
State     : Stopped
Status    : OK

C'est évidemment juste un exemple, mais vous pouvez voir que le résultat n'est pas remarquable pour un rapport de gestion. Ce que je cherche, c'est le nom du service et le StartName, qui est le compte sur lequel le service s'exécute. J'aimerais également que le rapport s'affiche dans un format plus clair, au lieu de cette liste difficile à lire. C'est là où les géniaux cmdlets de formatage et de filtrage de données de Windows PowerShell entrent en jeu.

Obtention des données dont vous avez besoin

Je commence par filtrer les données de Get-WMIObject pour que les propriétés qui m'intéressent s'affichent. La meilleure façon de le faire, c'est d'utiliser le cmdlet Select-Object de Windows PowerShell ou son alias abrégé, select. Select est conçu pour accepter une collection d'objets, comme la collection renvoyée par Get-WMIObject, et afficher uniquement les propriétés désirées de ces objets. Cela signifie que je peux canaliser la production de gwmi pour sélectionner et spécifier les deux propriétés qui m'intéressent. La figure 2 indique les résultats, qui incluent les propriétés Name et StartName bien formatées sous forme de tableau.

Figure 2 Affichage uniquement des propriétés Name et StartName dans un tableau

Figure 2 Affichage uniquement des propriétés Name et StartName dans un tableau (Cliquer sur l'image pour l'agrandir)

Toutefois, si je produisais ce rapport pour un audit de conformité, il contiendrait vraiment trop d'informations. Certains des services sont désactivés : il est probable qu'une personne lisant ces résultats ne s'intéresserait pas au compte que les services désactivés utiliseraient théoriquement. Ainsi, j'aimerais éliminer tous services qui ont un type de démarrage de Disabled, la propriété StartMode de la classe Win32_Service.

Windows PowerShell exécute un filtrage d'objets en utilisant le cmdlet Where-Object, ou son alias abrégé, where. Le cmdlet where accepte une collection d'objets d'entrée et les passe chacun dans un scriptblock pour déterminer si chaque objet sera présent dans la production du cmdlet, en se basant sur une série de critères définis. Chaque objet qui répond aux critères produit une comparaison True, et il est inclus dans la production ; les objets qui produisent une valeur False sont exclus.

J'ai donc décidé qu'il me fallait uniquement les objets dont la propriété StartMode est égale à Disabled. Sous Windows PowerShell, cette évaluation ressemble à ceci :

$object.StartMode –eq “Disabled”

Bien sûr, $object n'est qu'un exemple. Je n'écris pas vraiment un script, donc je n'ai pas de variable appelée $object. Dans le scriptblock utilisé par where, cependant, je peux utiliser une variable spéciale nommée $_, qui représente l'objet en cours d'évaluation par le cmdlet. Donc mon scriptblock de where pourrait avoir l'air de ceci :

$_.StartMode –eq “Disabled”

Il m'est assez facile de le tester :

PS C:\> gwmi win32_service | where 
{$_.StartMode -eq “Disabled”}

ExitCode  : 1077
Name      : Alerter
ProcessId : 0
StartMode : Disabled
State     : Stopped
Status    : OK

Bien sûr, dans ce test rapide, la production est présentée dans le style de liste par défaut. Et, pour gagner de l'espace, j'y ai inclus un seul service. Mais vous remarquerez que ce résultat est à l'envers. J'ai inclus les services désactivés, au lieu de les exclure. C'est parce que je me suis trompé de sens dans mon scriptblock : je dois inclure tous les services dont le StartMode est différent de Disabled, comme indiqué par cette modification à mon exemple :

PS C:\> gwmi win32_service | where 
{$_.StartMode -ne “Disabled”}

ExitCode  : 0
Name      : AcrSch2Svc
ProcessId : 1712
StartMode : Auto
State     : Running
Status    : OK

C'est mieux ! Maintenant que la production contient seulement les services qui m'intéressent, je peux de nouveau canaliser la production pour sélectionner et spécifier uniquement les propriétés que je veux :

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | select name,startname

Cette canalisation des données d'un cmdlet à un autre, puis encore à un autre, sert juste à illustrer les capacités de Windows PowerShell. Je n'ai toujours pas écrit de script, mais j'ai réussi à filtrer un grand ensemble de données pour obtenir uniquement la production que je voulais.

La bonne présentation

N'oubliez pas que la production de select consiste toujours en un paquet d'objets. Lorsque je récupère un tableau bien formaté en utilisant Windows PowerShell, il s'agit simplement de l'interprétation faite par PowerShell.exe de ces objets. En d'autres termes, Windows PowerShell sait que, en pauvre humain, je ne peux pas voir les objets, donc il les affiche sous la forme de texte. Dans ce cas, il a affiché les objets sous la forme d'un tableau, avec une colonne pour chaque propriété, comme illustré dans la figure 2.

Ce sera peut-être suffisant pour mon objectif d'audit. Ou peut-être pas, après tout ! Tout le monde a des besoins différents et Windows PowerShell ne prétend pas savoir quels sont vos besoins spécifiques. Au lieu de cela, il vous fournit les outils qui vous serviront à formater la sortie à votre guise. Quatre cmdlets incorporés (Format-List, Format-Custom, Format-Table et Format-Wide) sont conçus pour accepter une collection d'objets (comme la collection renvoyée par select) et formater ces objets de diverses façons. Format-Table est en fait ce qu'utilise déjà Windows PowerShell pour formater la production de mon cmdlet select. Pour une présentation différente, essayons Format-List :

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | format-list

Le résultat ressemble un peu à cet exemple :

name      : AcrSch2Svc
startname : LocalSystem

name      : Adobe LM Service
startname : LocalSystem

Le cmdlet Format-Large est conçu pour produire par défaut une liste à plusieurs colonnes de la première propriété de chaque objet. Prenez cette ligne, par exemple :

gwmi win32_service | where {$_.StartMode -ne “Disabled”} |
 select name,startname | format-wide

Il produit une liste de noms de service, mais ce n'est pas ce que je veux. Il manque le StartName dans le résultat (voir la figure 3), alors que c'est une information importante dont j'ai besoin pour mon rapport d'audit.

Figure 3 Le résultat affiché à l'aide du cmdlet Format-Wide n'inclut pas une information clé : le StartName.

Figure 3 Le résultat affiché à l'aide du cmdlet Format-Wide n'inclut pas une information clé : le StartName. (Cliquer sur l'image pour l'agrandir)

Puisque je m'occupe seulement de deux propriétés, il est probable que Format-Table ou Format-List soient acceptables. Mais il est peu probable qu'un auditeur soit content de lire ces informations sur l'écran. Il préférerait probablement un fichier.

Exportation des données

Alors, sous quelle forme un auditeur souhaiterait-il voir les données ? Il suffirait probablement d'exporter la liste des services et des identifiants de connexion vers un fichier CSV (valeurs séparées par une virgule), car ce fichier pourrait ensuite être ouvert dans Microsoft Excel®. Pour créer un fichier CSV, canalisez simplement votre sortie vers le cmdlet Export-CSV de Windows PowerShell :

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | export-csv c:\services.csv

Bien sûr, un fichier CSV semble un peu démodé, de nos jours. Peut-être que vos auditeurs préféreraient que les données soient affichées sous la forme d'une page Web sur un serveur intranet. Pour ce faire, commencez par convertir la production en HTML, en utilisant le cmdlet ConvertTo-HTML :

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | convertto-html

Le HTML brut est difficile à lire : il vous faudra donc écrire la sortie dans un fichier :

gwmi win32_service | where {$_.StartMode -ne “Disabled”} | 
select name,startname | convertto-html | out-file c:\services.html

Le résultat, illustré dans la figure 4, est une page HTML bien formatée qui peut être publiée sur n'importe quel serveur Web sans modification supplémentaire.

Figure 4 Production affichée sous la forme d'une page HTML bien formatée

Figure 4 Production affichée sous la forme d'une page HTML bien formatée (Cliquer sur l'image pour l'agrandir)

Les faits, rien que les faits (pertinents)

Windows PowerShell vous fournit un accès rapide à une grande plage de données de gestion. Cependant, ces données dans leur état brut ne sont pas toujours utiles pour une utilisation professionnelle.

En filtrant les données (à l'aide de where), en choisissant les propriétés d'objet désirées (à l'aide de select) et en appliquant une option de formatage appropriée (comme Format-Table ou Format-List), vous pouvez transformer rapidement ces données de gestion en informations utiles avec très peu d'efforts. Et ensuite, en exportant les données dans un format de fichier pouvant être facilement partagé, vous pouvez transmettre ces informations au-delà de votre propre ordinateur et communiquer de précieuses informations aux autres employés de votre entreprise.

Don Jones est directeur des projets et services de SAPIEN Technologies et co-auteur de Windows PowerShell : TFM (SAPIEN Press). Pour contacter Don, rendez-vous sur son site Web à l'adresse suivante : www.ScriptingAnswers.com.

© 2008 Microsoft Corporation et CMP Media, LLC. Tous droits réservés. Toute reproduction, totale ou partielle, est interdite sans autorisation préalable.