Alles wat u wilde weten over PSCustomObject

author
8 minutes, 21 seconds Read
  • 10/05/2020
  • 8 minuten om te lezen
    • j
    • m
    • s
    • j
    • c

PSCustomObjects zijn een geweldige tool om toe te voegen aan uw PowerShell-gereedschapsriem. Laten we beginnen met de basis en ons een weg banen naar de meer geavanceerde functies. Het idee achter het gebruik van een PSCustomObject is om een eenvoudige manier te hebben om gestructureerde gegevens te maken. Bekijk het eerste voorbeeld en u krijgt een beter idee van wat dat betekent.

Note

De oorspronkelijke versie van dit artikel verscheen op de blog geschreven door @KevinMarquette. Het PowerShell-team dankt Kevin voor het delen van deze inhoud met ons. Bekijk zijn blog op PowerShellExplained.com.

Creating a PSCustomObject

Ik ben dol op het gebruik van in PowerShell. Het maken van een bruikbaar object is nog nooit zo eenvoudig geweest.Daarom ga ik alle andere manieren waarop je een object kunt maken overslaan, maar ik moet wel vermelden dat de meeste van deze voorbeelden PowerShell v3.0 en nieuwer zijn.

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

Deze methode werkt goed voor mij, omdat ik hashtables voor zo ongeveer alles gebruik. Maar er zijn momenten waarop ik zou willen dat PowerShell hashtables meer als een object behandelt. Het eerste verschil merk je wanneer je Format-Table of Export-CSV wilt gebruiken en je beseft dat een hashtable gewoon een verzameling sleutel/waarde-paren is.

Je kunt de waarden dan benaderen en gebruiken zoals je een normaal object zou gebruiken.

$myObject.Name

Een hashtable converteren

Nu ik het er toch over heb, wist je dat je dit kon doen:

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

Ik geef er de voorkeur aan om het object vanaf het begin te maken, maar er zijn momenten dat je eerst met een hashtable moet werken. Dit voorbeeld werkt omdat de constructor een hashtable neemt voor de objecteigenschappen. Een belangrijke opmerking is dat hoewel deze methode werkt, het geen exact equivalent is. Het grootste verschil is dat de volgorde van de eigenschappen niet bewaard blijft.

Legacy benadering

Je hebt misschien gezien dat mensen New-Object gebruiken om aangepaste objecten te maken.

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

Deze manier is een stuk langzamer, maar het kan uw beste optie zijn op vroege versies van PowerShell.

Opslaan in een bestand

Ik vind de beste manier om een hashtable op te slaan in een bestand is door het op te slaan als JSON. U kunt deze dan weer importeren in een

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

Ik bespreek meer manieren om objecten in een bestand op te slaan in mijn artikel over De vele manieren om naar bestanden te lezen en te schrijven.

Werken met eigenschappen

Eigenschappen toevoegen

Je kunt nog steeds nieuwe eigenschappen aan je PSCustomObject toevoegen met Add-Member.

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

Eigenschappen verwijderen

Je kunt ook eigenschappen van een object verwijderen.

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

De psobject is een verborgen eigenschap die u toegang geeft tot de metadata van het basisobject.

Eigenschappen opnoemen

Soms hebt u een lijst nodig van alle namen van eigenschappen op een object.

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

We kunnen deze zelfde lijst ook uit de psobject eigenschap halen.

$myobject.psobject.properties.name

Dynamische toegang tot eigenschappen

Ik heb al gezegd dat je de waarden van eigenschappen direct kunt benaderen.

$myObject.Name

Je kunt een string gebruiken voor de property naam en het zal nog steeds werken.

$myObject.'Name'

We kunnen nog een stap verder gaan en een variabele gebruiken voor de property naam.

$property = 'Name'$myObject.$property

Ik weet dat het er vreemd uitziet, maar het werkt.

Verander PSCustomObject in een hashtable

Om verder te gaan met de laatste sectie, kun je dynamisch de eigenschappen doorlopen en er een hashtable van maken.

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

Testen op eigenschappen

Als je moet weten of een eigenschap bestaat, zou je gewoon kunnen controleren of die eigenschap een waarde heeft.

if( $null -ne $myObject.ID )

Maar als de waarde $null zou kunnen zijn, kunt u controleren of die bestaat door depsobject.properties ervoor te controleren.

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

Eigenschappen van objecten toevoegen

Als u een scriptmethode aan een object moet toevoegen, kunt u dat doen met Add-Member en eenScriptBlock. Je moet de this automatische variabele gebruiken om naar het huidige object te verwijzen. Hier is ascriptblock om een object in een hashtable te veranderen. (Dezelfde code als in het laatste voorbeeld)

Dan voegen we het toe aan ons object als een script property.

Dan kunnen we onze functie zo aanroepen:

$myObject.ToHashtable()

Objects vs Value types

Objects en value types gaan niet op dezelfde manier om met variabele toewijzingen. Als je waardetypen aan elkaar toewijst, wordt alleen de waarde naar de nieuwe variabele gekopieerd.

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

In dit geval is $first 1 en $second is 2.

Object-variabelen bevatten een verwijzing naar het eigenlijke object. Wanneer u een object toewijst aan een nieuwe variabele, verwijzen ze nog steeds naar hetzelfde object.

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

Omdat $third en $fourth verwijzen naar dezelfde instantie van een object, zijn zowel $third.key als$fourth.Key 4.

psobject.copy()

Als u een echte kopie van een object nodig hebt, kunt u het klonen.

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

Kloon maakt een oppervlakkige kopie van het object. Ze hebben nu verschillende instanties en $third.key is 3 en $fourth.Key is 4 in dit voorbeeld.

Ik noem dit een ondiepe kopie omdat als je geneste objecten hebt. (waar de eigenschappen andere objecten bevatten). Alleen de top-level waarden worden gekopieerd. De kind-objecten zullen naar elkaar verwijzen.

PSTypeName voor aangepaste object-typen

Nu we een object hebben, zijn er nog een paar dingen die we ermee kunnen doen die misschien niet zo voor de hand liggen. Het eerste wat we moeten doen is het een PSTypeName geven. Dit is de meest voorkomende manier waarop ik mensen het zie doen:

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

Ik ontdekte onlangs een andere manier om dit te doen van deze post door /u/markekraus. Ik deed een littledigging en meer berichten over het idee van Adam Bertram en Mike Shepard waar ze praten over deze aanpak die u toelaat om het te definiëren inline.

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

Ik hou van hoe mooi dit gewoon past in de taal. Nu we een object met een juiste typenaam hebben, kunnen we nog wat meer dingen doen.

Note

U kunt ook aangepaste PowerShell-typen maken met PowerShell-klassen. Zie voor meer informatiePowerShell Class Overview.

Gebruik DefaultPropertySet (de lange weg)

PowerShell bepaalt voor ons welke eigenschappen standaard moeten worden weergegeven. Veel van de native commando’s hebben een.ps1xml opmaakbestand dat al het zware werk doet. Uit deze post van Boe Prox, is er een andere manier voor ons om dit te doen op ons aangepaste object met alleen PowerShell. We kunnen het eenMemberSet geven om te gebruiken.

Nu wanneer mijn object gewoon in de shell valt, zal het standaard alleen die eigenschappen laten zien.

Update-TypeData met DefaultPropertySet

Dit is leuk, maar ik zag onlangs een betere manier toen ik keek naarPowerShell unplugged 2016 met Jeffrey Snover & Don Jones. Jeffrey gebruikteUpdate-TypeData om de standaardeigenschappen op te geven.

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

Dat is eenvoudig genoeg dat ik het bijna zou kunnen onthouden als ik deze post niet als snelverwijzing had. Nu kan ik gemakkelijk objecten maken met veel eigenschappen en het toch een mooi overzicht geven als ik er vanuit de commandoregel naar kijk. Als ik die andere eigenschappen nodig heb, zijn ze er nog steeds.

$myObject | Format-List *

Update-TypeData met ScriptProperty

Siets anders wat ik uit die video haalde was het maken van script eigenschappen voor je objecten. Dit is een goed moment om erop te wijzen dat dit ook werkt voor bestaande objecten.

Je kunt dit doen voordat je object is gemaakt of erna en het zal nog steeds werken. Dit is wat dit anders maakt dan het gebruik van Add-Member met een script eigenschap. Wanneer je Add-Member gebruikt op de manier waarnaar ik eerder verwees, bestaat het alleen op die specifieke instantie van het object. Deze is van toepassing op alle objecten met deze TypeName.

Functie parameters

U kunt nu deze aangepaste types gebruiken voor parameters in uw functies en scripts. U kunt een functie deze aangepaste objecten laten maken en ze dan aan andere functies doorgeven.

param( $Data )

PowerShell vereist dat het object het type is dat u hebt opgegeven. Als het type niet overeenkomt, wordt automatisch een validatiefout gemaakt, zodat u dit niet in uw code hoeft te testen. Een mooi voorbeeld van PowerShell laten doen waar het goed in is.

Functie OutputType

U kunt ook een OutputType definiëren voor uw geavanceerde functies.

function Get-MyObject{ param ( ...

De waarde van het OutputType-attribuut is slechts een documentatie-notitie. Ze wordt niet afgeleid van de functiecode of vergeleken met de eigenlijke uitvoer van de functie.

De belangrijkste reden waarom u een uitvoertype zou gebruiken, is dat de meta-informatie over uw functie uw bedoelingen weerspiegelt. Dingen zoals Get-Command en Get-Help waar uw ontwikkelomgeving gebruik van kan maken. Als je meer informatie wilt, kijk dan in de help voor het: about_Functions_OutputTypeAttribute.

Met dat gezegd hebbende, als je Pester gebruikt om je functies te testen, zou het een goed idee zijn om te valideren dat de output objecten overeenkomen met je OutputType. Dit zou variabelen kunnen vangen die gewoon op de pijp vallen wanneer dat niet zou moeten.

Dichtende gedachten

De context van dit alles ging over , maar veel van deze informatie is van toepassing op objecten in het algemeen.

Ik heb de meeste van deze functies eerder in het voorbijgaan gezien, maar ik heb ze nooit gepresenteerd gezien als een verzameling van informatie over PSCustomObject. Vorige week nog kwam ik er nog een tegen en was verbaasd dat ik die niet eerder had gezien. Ik wilde al deze ideeën samenbrengen zodat je hopelijk het grotere plaatje kunt zien en je ervan bewust kunt zijn als je de kans hebt om ze te gebruiken. Ik hoop dat je er iets van leert en een manier vindt om dit in je scripts te verwerken.

Similar Posts

Geef een antwoord

Het e-mailadres wordt niet gepubliceerd.