- 10/05/2020
- 8 minutes à lire
-
- j
- m
- s
- j
- c
.
PSCustomObject
s sont un excellent outil à ajouter à votre ceinture d’outils PowerShell. Commençons par les principes de base et progressons vers les fonctionnalités plus avancées. L’idée derrière l’utilisation d’un PSCustomObject
est d’avoir un moyen simple de créer des données structurées. Jetez un œil au premier exemple et vous aurez une meilleure idée de ce que cela signifie.
Note
La version originale de cet article est apparue sur le blog écrit par @KevinMarquette. L’équipe dePowerShell remercie Kevin d’avoir partagé ce contenu avec nous. Veuillez consulter son blog àPowerShellExplained.com.
- Création d’un PSCustomObject
- Conversion d’un hashtable
- Approche héritée
- Enregistrement dans un fichier
- Travailler avec les propriétés
- Ajouter des propriétés
- Supprimer des propriétés
- Enumération des noms de propriétés
- Accès dynamique aux propriétés
- Convertir PSCustomObject en une table de hachage
- Tester les propriétés
- Ajouter des méthodes d’objet
- Objets vs Types de valeur
- psobject.copy()
- PSTypeName pour les types d’objets personnalisés
- Utilisation de DefaultPropertySet (le long chemin)
- Update-TypeData avec DefaultPropertySet
- Update-TypeData avec ScriptProperty
- Paramètres de fonction
- Function OutputType
- Pensées finales
Création d’un PSCustomObject
J’adore utiliser dans PowerShell. Créer un objet utilisable n’a jamais été aussi facile.Pour cette raison, je vais passer en revue toutes les autres façons dont vous pouvez créer un objet, mais je dois mentionner que la plupart de ces exemples sont PowerShell v3.0 et plus récents.
$myObject = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
Cette méthode fonctionne bien pour moi parce que j’utilise des hashtables pour à peu près tout. Mais il y a des moments où j’aimerais que PowerShell traite les hashtables plus comme un objet. Le premier endroit où vous remarquez la différence est lorsque vous voulez utiliser Format-Table
ou Export-CSV
et que vous réalisez que le ahashtable est juste une collection de paires clé/valeur.
Vous pouvez alors accéder et utiliser les valeurs comme vous le feriez avec un objet normal.
$myObject.Name
Conversion d’un hashtable
Pendant que je suis sur le sujet, saviez-vous que vous pouviez faire ceci :
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = $myHashtable
Je préfère effectivement créer l’objet dès le début mais il y a des fois où vous devez travailler avec ahashtable d’abord. Cet exemple fonctionne parce que le constructeur prend un hashtable pour les objectproperties. Il est important de noter que si cette méthode fonctionne, elle n’est pas exactement équivalente. La plus grande différence est que l’ordre des propriétés n’est pas préservé.
Approche héritée
Vous avez peut-être vu des gens utiliser New-Object
pour créer des objets personnalisés.
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = New-Object -TypeName PSObject -Property $myHashtable
Cette façon est assez lente mais elle peut être votre meilleure option sur les premières versions de PowerShell.
Enregistrement dans un fichier
Je trouve que la meilleure façon d’enregistrer une table de hachage dans un fichier est de l’enregistrer en JSON. Vous pouvez le réimporter dans un
$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path$myObject = Get-Content -Path $Path | ConvertFrom-Json
Je couvre d’autres façons d’enregistrer des objets dans un fichier dans mon article surLes nombreuses façons de lire et d’écrire dans des fichiers.
Travailler avec les propriétés
Ajouter des propriétés
Vous pouvez toujours ajouter de nouvelles propriétés à votre PSCustomObject
avec Add-Member
.
$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'$myObject.ID
Supprimer des propriétés
Vous pouvez également supprimer des propriétés d’un objet.
$myObject.psobject.properties.remove('ID')
Le psobject
est une propriété cachée qui vous donne accès aux métadonnées de l’objet de base.
Enumération des noms de propriétés
Parfois, vous avez besoin d’une liste de tous les noms de propriétés sur un objet.
$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
On peut aussi obtenir cette même liste à partir de la propriété psobject
.
$myobject.psobject.properties.name
Accès dynamique aux propriétés
J’ai déjà mentionné que vous pouvez accéder directement aux valeurs des propriétés.
$myObject.Name
Vous pouvez utiliser une chaîne de caractères pour le nom de la propriété et cela fonctionnera toujours.
$myObject.'Name'
Nous pouvons faire un pas de plus et utiliser une variable pour le nom de la propriété.
$property = 'Name'$myObject.$property
Je sais que cela semble étrange, mais cela fonctionne.
Convertir PSCustomObject en une table de hachage
Pour continuer sur la dernière section, vous pouvez marcher dynamiquement sur les propriétés et créer une table de hachage à partir de celles-ci.
$hashtable = @{}foreach( $property in $myobject.psobject.properties.name ){ $hashtable = $myObject.$property}
Tester les propriétés
Si vous avez besoin de savoir si une propriété existe, vous pourriez simplement vérifier que cette propriété a une valeur.
if( $null -ne $myObject.ID )
Mais si la valeur peut être $null
, vous pouvez vérifier si elle existe en vérifiant lepsobject.properties
pour elle.
if( $myobject.psobject.properties.match('ID').Count )
Ajouter des méthodes d’objet
Si vous avez besoin d’ajouter une méthode de script à un objet, vous pouvez le faire avec Add-Member
et unScriptBlock
. Vous devez utiliser la variable automatique this
référençant l’objet courant. Voici unscriptblock
pour transformer un objet en une table de hachage. (même code form le dernier exemple)
Puis nous l’ajoutons à notre objet comme une propriété de script.
Puis nous pouvons appeler notre fonction comme ceci:
$myObject.ToHashtable()
Objets vs Types de valeur
Les objets et les types de valeur ne gèrent pas les affectations de variables de la même manière. Si vous assignez des types de valeur l’un à l’autre, seule la valeur est copiée dans la nouvelle variable.
$first = 1$second = $first$second = 2
Dans ce cas, $first
vaut 1 et $second
vaut 2.
Les variables d’objet contiennent une référence à l’objet réel. Lorsque vous assignez un objet à une nouvelle variable, ils font toujours référence au même objet.
$third = @{Key=3}$fourth = $third$fourth.Key = 4
Parce que $third
et $fourth
font référence à la même instance d’un objet, $third.key
et$fourth.Key
valent tous deux 4.
psobject.copy()
Si vous avez besoin d’une vraie copie d’un objet, vous pouvez le cloner.
$third = @{Key=3}$fourth = $third.psobject.copy()$fourth.Key = 4
Clone crée une copie superficielle de l’objet. Ils ont maintenant des instances différentes et $third.key
est 3et $fourth.Key
est 4 dans cet exemple.
J’appelle cela une copie superficielle car si vous avez des objets imbriqués. (où les propriétés contiennent d’autres objets). Seules les valeurs de niveau supérieur sont copiées. Les objets enfants feront référence les uns aux autres.
PSTypeName pour les types d’objets personnalisés
Maintenant que nous avons un objet, il y a quelques choses supplémentaires que nous pouvons faire avec lui qui peuvent ne pas être aussi évidentes. La première chose que nous devons faire est de lui donner un PSTypeName
. C’est la façon la plus courante dont je vois les gens le faire :
$myObject.PSObject.TypeNames.Insert(0,"My.Object")
J’ai récemment découvert une autre façon de le faire grâce à ce post de /u/markekraus. J’ai fait un peu de recherche et plus de posts sur l’idée d’Adam Bertram et Mike Shepard où ils parlent de cette approche qui vous permet de le définir en ligne.
$myObject = @{ PSTypeName = 'My.Object' Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
J’aime comment joliment cela s’intègre juste dans le langage. Maintenant que nous avons un objet avec un typename approprié, nous pouvons faire d’autres choses.
Note
Vous pouvez également créer des types PowerShell personnalisés en utilisant des classes PowerShell. Pour plus d’informations, voirPowerShell Class Overview.
Utilisation de DefaultPropertySet (le long chemin)
PowerShell décide pour nous des propriétés à afficher par défaut. Beaucoup de commandes natives ont un.ps1xml
fichier de formatage qui fait tout le travail lourd. D’après ce post de Boe Prox, il y a un autre moyen pour nous de faire cela sur notre objet personnalisé en utilisant seulement PowerShell. Nous pouvons lui donner unMemberSet
pour qu’il l’utilise.
Maintenant quand mon objet tombe juste dans le shell, il ne montrera que ces propriétés par défaut.
Update-TypeData avec DefaultPropertySet
C’est bien mais j’ai récemment vu une meilleure façon en regardantPowerShell unplugged 2016 avec Jeffrey Snover & Don Jones. Jeffrey utilisaitUpdate-TypeData pour spécifier les propriétés par défaut.
$TypeData = @{ TypeName = 'My.Object' DefaultDisplayPropertySet = 'Name','Language'}Update-TypeData @TypeData
C’est assez simple pour que je puisse presque m’en souvenir si je n’avais pas ce post comme référence rapide. Maintenant, je peux facilement créer des objets avec beaucoup de propriétés et toujours leur donner une belle vue propre en les regardant depuis le shell. Si j’ai besoin d’accéder ou de voir ces autres propriétés, elles sont toujours là.
$myObject | Format-List *
Update-TypeData avec ScriptProperty
Autre chose que j’ai retirée de cette vidéo, c’est la création de propriétés de script pour vos objets. Ce serait un bon moment pour souligner que cela fonctionne aussi pour les objets existants.
Vous pouvez faire cela avant que votre objet soit créé ou après et cela fonctionnera toujours. C’est ce qui rend ceci différent de l’utilisation de Add-Member
avec une propriété de script. Lorsque vous utilisez Add-Member
de la manière Ireferenced plus tôt, il n’existe que sur cette instance spécifique de l’objet. Celle-ci s’applique à tous les objets avec ce TypeName
.
Paramètres de fonction
Vous pouvez maintenant utiliser ces types personnalisés pour les paramètres dans vos fonctions et vos scripts. Vous pouvez faire en sorte qu’unefonction crée ces objets personnalisés et les passe ensuite dans d’autres fonctions.
param( $Data )
PowerShell exige que l’objet soit du type que vous avez spécifié. Il jette une erreur de validation si le type ne correspond pas automatiquement pour vous épargner l’étape de test pour cela dans votre code. Un excellent exemple de laisser PowerShell faire ce qu’il fait le mieux.
Function OutputType
Vous pouvez également définir un OutputType
pour vos fonctions avancées.
function Get-MyObject{ param ( ...
La valeur de l’attribut OutputType est seulement une note de documentation. Elle n’est pas dérivée du code de la fonction ou comparée à la sortie réelle de la fonction.
La principale raison pour laquelle vous utiliseriez un type de sortie est que les méta-informations sur votre fonctionreflètent vos intentions. Des choses comme Get-Command
et Get-Help
dont votre environnement de développement peut tirer parti. Si vous voulez plus d’informations, alors jetez un coup d’œil à l’aide pour cela:about_Functions_OutputTypeAttribute.
Avec cela dit, si vous utilisez Pester pour tester l’unité de vos fonctions, alors ce serait une bonne idée de valider les objets de sortie correspondent à votre OutputType. Cela pourrait attraper les variables qui tombent juste sur le tuyau quand elles ne devraient pas.
Pensées finales
Le contexte de ceci était tout au sujet de , mais beaucoup de ces informations s’appliquent aux objets en général.
J’ai vu la plupart de ces fonctionnalités en passant avant mais je ne les ai jamais vues présentées comme une collection d’informations sur PSCustomObject
. Juste la semaine dernière, je suis tombé sur une autre et j’ai été surpris de ne pas l’avoir vue avant. J’ai voulu rassembler toutes ces idées pour que vous puissiez, je l’espère, voir la vue d’ensemble et en être conscient lorsque vous aurez l’occasion de les utiliser. J’espère que vous avez appris quelque chose et que vous pourrez trouver un moyen d’intégrer ces idées dans vos scripts.