Qu'est-ce que Windows PowerShell et que mange-t-il? Partie 4: Travailler avec des objets, des classes personnalisées



La sortie texte des commandes dans la fenêtre de l'interpréteur PowerShell n'est qu'un moyen d'afficher des informations sous une forme lisible par l'homme. En fait, l'environnement est axé sur le travail avec les objets: les applets de commande et les fonctions les reçoivent en entrée et retournent en sortie , et les types de variables disponibles en mode interactif et dans les scripts sont basés sur des classes .NET. Dans le quatrième article du cycle, nous étudierons plus en détail le travail avec les objets.

Table des matières:


PowerShell




ForEach-Object, Group-Object Measure-Object
.NET COM (New-Object)

PSCustomObject


PowerShell


Rappelons qu'un objet est une collection de champs de données (propriétés, événements, etc.) et leurs méthodes de traitement (méthodes). Sa structure est déterminée par le type, qui est généralement basé sur les classes utilisées dans la plate-forme unifiée .NET Core. Il est également possible de travailler avec des objets COM, CIM (WMI) et ADSI. Des propriétés et des méthodes sont nécessaires pour effectuer diverses actions sur les données, en plus de PowerShell, les objets peuvent être passés comme arguments aux fonctions et applets de commande, des valeurs assignées aux variables, et il existe également un mécanisme pour composer des commandes (pipeline ou pipeline). Chaque commande du pipeline transmet à son tour la sortie à la suivante - objet par objet. Pour le traitement, vous pouvez utiliser des applets de commande compilées ou créer vos propres fonctions avancéespour effectuer diverses manipulations avec des objets dans le pipeline: filtrage, tri, regroupement et même modification de leur structure. Le transfert de données sous cette forme présente un sérieux avantage: l'équipe réceptrice n'a pas besoin d'analyser le flux d'octets (texte), toutes les informations nécessaires sont facilement extraites en se référant aux propriétés et méthodes correspondantes.

Afficher la structure de l'objet


Par exemple, exécutez l'applet de commande Get-Process, qui vous permet d'obtenir des informations sur les processus en cours d'exécution dans le système:



il affiche des données texte formatées qui ne donnent pas une idée des propriétés des objets renvoyés et de leurs méthodes. Pour affiner la sortie, vous devez apprendre à examiner la structure des objets, et l'applet de commande Get-Member nous aidera avec ceci:

Get-Process | Get-Member



Ici, nous voyons déjà le type et la structure, et à l'aide de paramètres supplémentaires, nous pouvons, par exemple, afficher uniquement les propriétés de l'objet qui est entré dans l'entrée:

Get-Process | Get-Member -MemberType Property

Cette connaissance sera nécessaire pour résoudre les tâches administratives de manière interactive ou pour écrire vos propres scripts: par exemple, pour obtenir des informations sur les processus bloqués par la propriété Responding.

Filtrage d'objets


PowerShell vous permet de diriger des objets qui satisfont une condition spécifique:

Where-Object {   }

Le résultat de l'exécution du bloc de script entre crochets opérateur doit être une valeur logique. S'il est vrai ($ true), l'objet qui est entré dans l'applet de commande Where-Object sera transmis dans le pipeline, sinon (la valeur $ false) il sera supprimé. Par exemple, nous répertorions les services Windows Server arrêtés, c'est-à-dire ceux dont la propriété Status est définie sur Arrêté:

Get-Service | Where-Object {$_.Status -eq "Stopped"}



Ici, nous voyons à nouveau la représentation textuelle, mais si vous voulez comprendre le type et la structure interne des objets passant par le pipeline, c'est facile:

Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member



Trier les objets


Lors du pipelining d'objets, il est souvent nécessaire de les trier. Les noms de propriété (clés de tri) sont passés à l'applet de commande Sort-Object et elle renvoie les objets classés par leurs valeurs. La sortie des processus en cours d'exécution peut être facilement triée en fonction du temps passé par le processeur (propriété cpu):

Get-Process | Sort-Object –Property cpu

Le paramètre -Property peut être omis lors de l'appel de l'applet de commande Sort-Object - il est utilisé par défaut. Pour le tri inverse, utilisez le paramètre -Descending:

Get-Process | Sort-Object cpu -Descending



Sélection d'objets et de leurs pièces


L'applet de commande Select-Object vous permet de sélectionner un nombre spécifique d'objets au début ou à la fin d'un pipeline à l'aide des paramètres -First ou -Last. Avec lui, vous pouvez sélectionner des objets uniques ou certaines propriétés, ainsi que créer de nouveaux objets sur leur base. Nous analyserons le travail de l'applet de commande à l'aide d'exemples simples.

La commande suivante affiche des informations sur 10 processus consommant la quantité maximale de RAM (propriété WS):

Get-Process | Sort-Object WS -Descending | Select-Object -First 10



Vous pouvez sélectionner uniquement certaines propriétés des objets passant par le pipeline et en créer de nouvelles en fonction de celles-ci:

Get-Process | Select-Object ProcessName, Id -First 1

À la suite du pipeline, nous obtiendrons un nouvel objet, dont la structure sera différente de la structure renvoyée par l'applet de commande Get-Process. Nous vérifierons cela en utilisant Get-Member:

Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member



Notez que Select-Object renvoie un seul objet (-First 1), qui n'a que deux champs spécifiés par nous: leurs valeurs ont été copiées du premier objet passé au pipeline avec l'applet de commande Get-Process. À l'aide de Select-Object, l'une des façons de créer des objets dans les scripts PowerShell est basée:

$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()



À l'aide de Select-Object, vous pouvez ajouter des propriétés calculées à des objets qui doivent être représentés sous forme de table de hachage . Dans ce cas, la valeur de sa première clé correspond au nom de la propriété, et la valeur de la seconde correspond à la valeur de la propriété pour l'élément courant du pipeline:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}



Regardons la structure des objets passant par le pipeline:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member



ForEach-Object, Group-Object et Measure-Object


Il existe d'autres applets de commande pour travailler avec des objets. Par exemple, nous parlerons des trois plus utiles:

ForEach-Object vous permet d'exécuter du code PowerShell pour chaque objet du pipeline:

ForEach-Object {   }

Group-Object regroupe les objets par valeur de propriété:

Group-Object PropertyName

Si vous l'exécutez avec le paramètre -NoElement, vous pouvez connaître le nombre d'éléments dans les groupes.

Measure-Object agrège divers paramètres récapitulatifs par les valeurs des champs d'objets dans le pipeline (calcule la somme et trouve également la valeur minimale, maximale ou moyenne):

Measure-Object -Property PropertyName -Minimum -Maximum -Average -Sum

En règle générale, les applets de commande considérées sont utilisées de manière interactive et les scripts créent souvent des fonctions avec des blocs Begin, Process et End.

Création d'objets .NET et COM (New-Object)


Il existe de nombreux composants logiciels avec des interfaces .NET Core et COM qui sont utiles aux administrateurs système. À l'aide de la classe System.Diagnostics.EventLog, vous pouvez gérer les journaux système directement à partir de Windows PowerShell. Voyons un exemple de création d'une instance de cette classe à l'aide de l'applet de commande New-Object avec le paramètre -TypeName:

New-Object -TypeName System.Diagnostics.EventLog



Comme nous n'avons pas spécifié de journal des événements spécifique, l'instance résultante de la classe ne contient aucune donnée. Pour changer cela, lors de sa création, vous devez appeler la méthode constructeur spéciale à l'aide du paramètre -ArgumentList. Si nous voulons accéder au journal des applications, passez la chaîne «Application» comme argument au constructeur:

$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog



Remarque: nous avons enregistré la sortie de la commande dans la variable $ AppLog. Bien que les pipelines soient couramment utilisés en mode interactif, les scripts nécessitent souvent de maintenir une référence d'objet. En outre, les principales classes .NET Core sont contenues dans l'espace de noms System: PowerShell recherche par défaut les types spécifiés dans celui-ci, donc écrire Diagnostics.EventLog au lieu de System.Diagnostics.EventLog est tout à fait correct.

Pour travailler avec le journal, vous pouvez vous référer aux méthodes appropriées:

$AppLog | Get-Member -MemberType Method



Disons qu'il est effacé à l'aide de la méthode Clear () avec des droits d'accès:

$AppLog.Clear()

L'applet de commande New-Object est également utilisée pour travailler avec des composants COM. Il y en a beaucoup - des bibliothèques fournies avec le serveur de script Windows aux applications ActiveX, comme par exemple Internet Explorer. Pour créer un objet COM, vous devez spécifier le paramètre -ComObject avec l'identificateur de programme ProgId de la classe souhaitée:

New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject

Pour créer vos propres objets avec une structure arbitraire, l'utilisation de New-Object semble trop archaïque et encombrante; cette applet de commande est utilisée pour travailler avec des composants logiciels externes à PowerShell. Dans les articles suivants, cette question sera discutée plus en détail. Outre les objets .NET et COM, nous découvrirons également les objets CIM (WMI) et ADSI.

Appel de méthodes statiques


Il n'est pas possible de créer des instances de certaines classes .NET Core: il s'agit notamment de System.Environment et System.Math. Ils sont statiques et contiennent uniquement des propriétés et des méthodes statiques. Il s'agit essentiellement de bibliothèques de référence qui sont utilisées sans créer d'objets. Vous pouvez faire référence à une classe statique via un littéral, en plaçant le nom du type entre crochets. De plus, si vous regardez la structure de l'objet à l'aide de Get-Member, nous verrons le type System.RuntimeType au lieu de System.Environment:

[System.Environment] | Get-Member



Pour afficher uniquement les éléments statiques, vous devez appeler Get-Member avec le paramètre -Static (faites attention au type d'objet):

[System.Environment] | Get-Member -Static



Pour accéder aux propriétés et méthodes statiques, deux deux points consécutifs sont utilisés au lieu d'un point après un littéral:

[System.Environment]::OSVersion

Ou

$test=[System.Math]::Sqrt(25) 
$test
$test.GetType()



Tapez PSCustomObject


Parmi les nombreux types de données disponibles dans PowerShell, il convient de mentionner PSCustomObject, conçu pour stocker des objets avec une structure arbitraire. La création d'un tel objet à l'aide de l'applet de commande New-Object est considérée comme une méthode classique, mais lourde et obsolète:

$object = New-Object  –TypeName PSCustomObject -Property @{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'}

Regardons la structure de l'objet:

$object | Get-Member



À partir de PowerShell 3.0, une autre syntaxe est disponible:

$object = [PSCustomObject]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

Vous pouvez accéder aux données de l'une des manières équivalentes:

$object.Name

$object.'Name'

$value = 'Name'
$object.$value

Voici un exemple de conversion d'une table de hachage existante en objet:

$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()



L'un des inconvénients des objets de ce type est que l'ordre de leurs propriétés peut changer. Pour éviter cela, vous devez utiliser l'attribut [commandé]:

$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

Il existe d'autres options pour créer un objet: nous avons examiné ci-dessus l'utilisation de l' applet de commande Select-Object . Il reste à traiter l'ajout et la suppression d'éléments. Faire cela pour l'objet de l'exemple précédent est assez simple:

$object | Add-Member –MemberType NoteProperty –Name Age  –Value 33
$object | Get-Member



L'applet de commande Add-Member vous permet d'ajouter non seulement des propriétés, mais également des méthodes à l'objet $ object créé précédemment à l'aide de la construction "-MemberType ScriptMethod":

$ScriptBlock = {
    #  
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member

Remarque: pour stocker le code de la nouvelle méthode, nous avons utilisé la variable $ ScriptBlock de type ScriptBlock.



Pour supprimer des propriétés, utilisez la méthode appropriée:

$object.psobject.properties.remove('Name')

Créer vos propres cours


PowerShell 5.0 introduit la possibilité de définir des classes à l'aide de la syntaxe caractéristique des langages de programmation orientés objet. Le mot de service Class est destiné à cela, après quoi vous devez spécifier le nom de la classe et décrire son corps entre crochets d'opérateur:

class MyClass
{
    #  
}

Il s'agit d'un véritable type de .NET Core, dont le corps décrit ses propriétés, ses méthodes et d'autres éléments. Prenons un exemple de définition de classe simple:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
}

Pour créer un objet (une instance d'une classe), utilisez l'applet de commande New-Object ou un littéral du type [MyClass] et la nouvelle méthode pseudostatique (constructeur par défaut):

$object = New-Object -TypeName MyClass

ou

$object = [MyClass]::new()

Analysons la structure de l'objet:

$object | Get-Member



N'oubliez pas la portée: vous ne pouvez pas faire référence au nom du type comme une chaîne ou utiliser un littéral de type en dehors du script ou du module dans lequel la classe est définie. En même temps, les fonctions peuvent renvoyer des instances de la classe (objets) qui seront disponibles en dehors du module ou du script.

Après avoir créé l'objet, remplissez ses propriétés:

$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object



Notez que dans la description de classe non seulement les types de propriétés sont définis, mais aussi leurs valeurs par défaut:

class Example
{
     [string]$Name = 'John Doe'
}

La description de la méthode de classe ressemble à la description d'une fonction, mais sans utiliser le mot fonction function. Comme dans la fonction, les paramètres sont passés aux méthodes, si nécessaire:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
     
     # 
     Smile([bool]$param1)
     {
         If($param1) {
            Write-Host ':)'
         }
     }
}

Maintenant, le représentant de notre classe sait sourire:

$object = [MyClass]::new()
$object.Smile($true)

Les méthodes peuvent être surchargées, de plus, la classe a des propriétés et des méthodes statiques , ainsi que des constructeurs dont les noms coïncident avec le nom de la classe elle-même. Une classe définie dans un script ou un module PowerShell peut servir de base à une autre - c'est ainsi que l'héritage est implémenté. Dans le même temps, l'utilisation des classes .NET existantes est autorisée en tant que classes de base:

class MyClass2 : MyClass
{
      #  ,     MyClass
}
[MyClass2]::new().Smile($true)

Notre description de l'utilisation d'objets dans PowerShell n'est pas exhaustive. Dans les publications suivantes, nous essaierons de l'approfondir avec des exemples pratiques: le cinquième article de la série sera consacré aux problèmes d'intégration de PowerShell avec des composants logiciels tiers. Les pièces passées peuvent être trouvées sur les liens ci-dessous.



1: Windows PowerShell
2: Windows PowerShell
3: ,


All Articles