Alles, was Sie über PSCustomObject wissen wollten

author
8 minutes, 15 seconds Read
  • 10/05/2020
  • 8 Minuten zu lesen
    • j
    • m
    • s
    • j
    • c

PSCustomObjectsind ein großartiges Werkzeug, das Sie in Ihren PowerShell-Werkzeuggürtel aufnehmen können. Beginnen wir mit den Grundlagen und arbeiten uns dann zu den fortgeschrittenen Funktionen vor. Die Idee hinter der Verwendung von PSCustomObject ist es, eine einfache Möglichkeit zur Erstellung strukturierter Daten zu haben. Schauen Sie sich das erste Beispiel an, damit Sie eine bessere Vorstellung davon bekommen, was das bedeutet.

Note

Die ursprüngliche Version dieses Artikels erschien im Blog von @KevinMarquette. DasPowerShell-Team dankt Kevin dafür, dass er diesen Inhalt mit uns geteilt hat. Bitte besuchen Sie seinen Blog unterPowerShellExplained.com.

Erstellen eines PSCustomObject

Ich liebe die Verwendung von in PowerShell. Aus diesem Grund überspringe ich alle anderen Möglichkeiten, ein Objekt zu erstellen, aber ich muss erwähnen, dass die meisten dieser Beispiele PowerShell v3.0 und neuer sind.

$myObject = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}

Diese Methode funktioniert gut für mich, weil ich Hash-Tabellen für fast alles verwende. Aber es gibt Momente, in denen ich möchte, dass PowerShell Hash-Tabellen eher wie ein Objekt behandelt. Der erste Punkt, an dem Sie den Unterschied bemerken, ist, wenn Sie Format-Table oder Export-CSV verwenden möchten und feststellen, dass eine Hashtabelle nur eine Sammlung von Schlüssel/Wert-Paaren ist.

Sie können dann auf die Werte wie auf ein normales Objekt zugreifen und sie verwenden.

$myObject.Name

Konvertieren einer Hashtabelle

Wenn ich schon beim Thema bin, wussten Sie, dass man das so machen kann:

$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = $myHashtable

Ich bevorzuge es, das Objekt von Anfang an zu erstellen, aber es gibt Zeiten, in denen man zuerst mit einer Hashtabelle arbeiten muss. Dieses Beispiel funktioniert, weil der Konstruktor eine Hashtabelle für die Objekteigenschaften nimmt. Ein wichtiger Hinweis ist, dass diese Methode zwar funktioniert, aber keine exakte Entsprechung ist. Der größte Unterschied besteht darin, dass die Reihenfolge der Eigenschaften nicht beibehalten wird.

Legacy-Ansatz

Sie haben vielleicht gesehen, dass Leute New-Object benutzerdefinierte Objekte erstellen.

$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = New-Object -TypeName PSObject -Property $myHashtable

Dieser Weg ist etwas langsamer, kann aber in frühen Versionen von PowerShell die beste Option sein.

Speichern in einer Datei

Ich finde, der beste Weg, eine Hashtabelle in einer Datei zu speichern, ist, sie als JSON zu speichern. Sie können sie dann wieder in eine

$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path$myObject = Get-Content -Path $Path | ConvertFrom-Json

Ich behandle weitere Möglichkeiten, Objekte in einer Datei zu speichern, in meinem Artikel über Die vielen Möglichkeiten, Dateien zu lesen und zu schreiben.

Arbeiten mit Eigenschaften

Hinzufügen von Eigenschaften

Sie können mit Add-Member noch neue Eigenschaften zu Ihrem PSCustomObject hinzufügen.

$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'$myObject.ID

Eigenschaften entfernen

Sie können auch Eigenschaften von einem Objekt entfernen.

$myObject.psobject.properties.remove('ID')

Die psobject ist eine verborgene Eigenschaft, die Ihnen den Zugriff auf die Metadaten des Basisobjekts ermöglicht.

Eigenschaftsnamen aufzählen

Manchmal benötigen Sie eine Liste aller Eigenschaftsnamen eines Objekts.

$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name

Die gleiche Liste können wir auch über die psobjectEigenschaft erhalten.

$myobject.psobject.properties.name

Dynamischer Zugriff auf Eigenschaften

Ich habe bereits erwähnt, dass man direkt auf Eigenschaftswerte zugreifen kann.

$myObject.Name

Sie können eine Zeichenkette für den Eigenschaftsnamen verwenden und es wird immer noch funktionieren.

$myObject.'Name'

Wir können einen Schritt weiter gehen und eine Variable für den Eigenschaftsnamen verwenden.

$property = 'Name'$myObject.$property

Ich weiß, das sieht seltsam aus, aber es funktioniert.

Konvertieren Sie PSCustomObject in eine Hashtabelle

Um mit dem letzten Abschnitt fortzufahren, können Sie die Eigenschaften dynamisch durchlaufen und daraus eine Hashtabelle erstellen.

$hashtable = @{}foreach( $property in $myobject.psobject.properties.name ){ $hashtable = $myObject.$property}

Prüfen auf Eigenschaften

Wenn Sie wissen müssen, ob eine Eigenschaft existiert, können Sie einfach prüfen, ob diese Eigenschaft einen Wert hat.

if( $null -ne $myObject.ID )

Wenn der Wert aber $null sein könnte, kann man prüfen, ob er existiert, indem man denpsobject.properties daraufhin überprüft.

if( $myobject.psobject.properties.match('ID').Count )

Hinzufügen von Objektmethoden

Wenn man eine Skriptmethode zu einem Objekt hinzufügen muss, kann man das mit Add-Member und einemScriptBlock tun. Sie müssen die automatische Variable this verwenden, die das aktuelle Objekt referenziert. Hier ist ascriptblock, um ein Objekt in eine Hashtabelle zu verwandeln. (derselbe Code wie im letzten Beispiel)

Dann fügen wir sie unserem Objekt als Skripteigenschaft hinzu.

Dann können wir unsere Funktion wie folgt aufrufen:

$myObject.ToHashtable()

Objekte vs. Werttypen

Objekte und Werttypen behandeln Variablenzuweisungen nicht auf die gleiche Weise. Wenn man Werttypen einander zuweist, wird nur der Wert in die neue Variable kopiert.

$first = 1$second = $first$second = 2

In diesem Fall ist $first die 1 und $second die 2.

Objektvariablen enthalten eine Referenz auf das eigentliche Objekt. Wenn du ein Objekt einer neuen Variablen zuweist, verweisen sie immer noch auf dasselbe Objekt.

$third = @{Key=3}$fourth = $third$fourth.Key = 4

Da $third und $fourth auf dieselbe Instanz eines Objekts verweisen, sind $third.key und $fourth.Key beide 4.

psobject.copy()

Wenn man eine echte Kopie eines Objekts braucht, kann man es klonen.

$third = @{Key=3}$fourth = $third.psobject.copy()$fourth.Key = 4

Clone erstellt eine flache Kopie des Objekts. Sie haben jetzt verschiedene Instanzen und $third.key ist 3 und $fourth.Key ist 4 in diesem Beispiel.

Ich nenne das eine flache Kopie, weil man verschachtelte Objekte hat. (wo die Eigenschaften andere Objekte enthalten). Es werden nur die Werte der obersten Ebene kopiert. Die untergeordneten Objekte referenzieren sich gegenseitig.

PSTypeName für benutzerdefinierte Objekttypen

Nun, da wir ein Objekt haben, gibt es ein paar weitere Dinge, die wir damit tun können, die vielleicht nicht so offensichtlich sind. Als erstes müssen wir ihm einen PSTypeName geben. Das ist die gängigste Methode, die ich kenne:

$myObject.PSObject.TypeNames.Insert(0,"My.Object")

Ich habe vor kurzem eine andere Methode entdeckt, die in diesem Beitrag von /u/markekraus beschrieben ist. Ich habe ein wenig nachgeforscht und weitere Beiträge über die Idee von Adam Bertram und Mike Shepard gefunden, in denen sie über diesen Ansatz sprechen, der es erlaubt, ihn inline zu definieren.

$myObject = @{ PSTypeName = 'My.Object' Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}

Ich finde es toll, wie gut das in die Sprache passt. Jetzt, da wir ein Objekt mit einem richtigen Typennamen haben, können wir einige weitere Dinge tun.

Hinweis

Sie können auch benutzerdefinierte PowerShell-Typen mit PowerShell-Klassen erstellen. Weitere Informationen finden Sie unterPowerShell-Klassenübersicht.

Verwenden von DefaultPropertySet (der lange Weg)

PowerShell entscheidet für uns, welche Eigenschaften standardmäßig angezeigt werden sollen. Viele der nativen Befehle haben eine.ps1xml Formatierungsdatei, die die ganze Arbeit übernimmt. Aus diesem Beitrag von Boe Prox geht hervor, dass es eine weitere Möglichkeit gibt, dies für unser benutzerdefiniertes Objekt nur mit PowerShell zu tun. Wir können ihm einMemberSet geben, das es verwenden soll.

Wenn mein Objekt jetzt einfach in die Shell fällt, zeigt es standardmäßig nur diese Eigenschaften an.

Update-TypeData mit DefaultPropertySet

Das ist schön, aber ich habe kürzlich eine bessere Möglichkeit gesehen, als ich mirPowerShell unplugged 2016 mit Jeffrey Snover & Don Jones angesehen habe. Jeffrey verwendeteUpdate-TypeData, um die Standardeigenschaften festzulegen.

$TypeData = @{ TypeName = 'My.Object' DefaultDisplayPropertySet = 'Name','Language'}Update-TypeData @TypeData

Das ist so einfach, dass ich es mir fast merken könnte, wenn ich nicht diesen Beitrag als Schnellreferenz hätte. Jetzt kann ich ganz einfach Objekte mit vielen Eigenschaften erstellen und sie trotzdem übersichtlich darstellen, wenn ich sie in der Shell betrachte. Wenn ich auf diese anderen Eigenschaften zugreifen oder sie sehen muss, sind sie immer noch da.

$myObject | Format-List *

Update-TypeData mit ScriptProperty

Etwas anderes, das ich aus diesem Video mitgenommen habe, ist das Erstellen von Skripteigenschaften für Ihre Objekte. Dies ist ein guter Zeitpunkt, um darauf hinzuweisen, dass dies auch für bestehende Objekte funktioniert.

Sie können dies tun, bevor Ihr Objekt erstellt wird oder danach und es wird immer noch funktionieren. Das ist der Unterschied zur Verwendung von Add-Member mit einer Skripteigenschaft. Wenn Sie Add-Member auf die oben beschriebene Weise verwenden, gilt es nur für diese spezielle Instanz des Objekts. Dies gilt für alle Objekte mit dieser TypeName.

Funktionsparameter

Sie können nun diese benutzerdefinierten Typen für Parameter in Ihren Funktionen und Skripten verwenden. Sie können eine Funktion diese benutzerdefinierten Objekte erstellen lassen und sie dann an andere Funktionen übergeben.

param( $Data )

PowerShell verlangt, dass das Objekt den von Ihnen angegebenen Typ hat. Wenn der Typ nicht übereinstimmt, wird automatisch ein Überprüfungsfehler ausgelöst, damit Sie sich den Schritt ersparen, in Ihrem Code darauf zu testen. Ein hervorragendes Beispiel dafür, dass PowerShell das tut, was es am besten kann.

Funktion OutputType

Sie können auch ein OutputType für Ihre erweiterten Funktionen definieren.

function Get-MyObject{ param ( ...

Der Wert des Attributs OutputType ist nur ein Dokumentationshinweis. Er wird nicht aus dem Funktionscode abgeleitet oder mit der tatsächlichen Funktionsausgabe verglichen.

Der Hauptgrund für die Verwendung eines Ausgabetyps ist, dass die Metainformationen über Ihre Funktion Ihre Absichten widerspiegeln. Dinge wie Get-Command und Get-Help, die Ihre Entwicklungsumgebung ausnutzen kann. Wenn du mehr Informationen möchtest, dann schau dir die Hilfe dazu an: about_Functions_OutputTypeAttribute.

Wenn du Pester zum Unit-Test deiner Funktionen verwendest, dann wäre es eine gute Idee, zu überprüfen, ob die Ausgabeobjekte mit deinem OutputType übereinstimmen. Dies könnte Variablen abfangen, die einfach in die Pipe fallen, wenn sie es nicht sollten.

Abschließende Gedanken

Der Kontext dieses Artikels bezog sich auf , aber viele dieser Informationen gelten für Objekte im Allgemeinen.

Ich habe die meisten dieser Funktionen schon einmal im Vorbeigehen gesehen, aber ich habe sie nie als eine Sammlung von Informationen über PSCustomObject gesehen. Erst in der letzten Woche bin ich über eine weitere Funktion gestolpert und war überrascht, dass ich sie noch nicht gesehen hatte. Ich wollte all diese Ideen zusammenfassen, damit Sie hoffentlich das Gesamtbild sehen und sich ihrer bewußt werden, wenn Sie die Gelegenheit haben, sie zu nutzen. Ich hoffe, Sie haben etwas gelernt und finden einen Weg, dies in Ihre Skripte zu integrieren.

Similar Posts

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.