Alt du ønskede at vide om PSCustomObject

author
8 minutes, 44 seconds Read
  • 10/05/2020
  • 8 minutter at læse
    • j
    • m
    • s
    • j
    • c

PSCustomObjects er et fantastisk værktøj til at tilføje i dit PowerShell-værktøjsbælte. Lad os starte med det grundlæggende og arbejde os ind på de mere avancerede funktioner. Ideen bag at bruge en PSCustomObject er at have en enkel måde at oprette strukturerede data på. Tag et kig på det første eksempel, og du vil få en bedre idé om, hvad det betyder.

Note

Den oprindelige version af denne artikel blev vist på bloggen skrevet af @KevinMarquette. PowerShell-teamet takker Kevin for at dele dette indhold med os. Tjek venligst hans blog påPowerShellExplained.com.

Skabelse af et PSCustomObject

Jeg elsker at bruge i PowerShell. Det har aldrig været nemmere at oprette et brugbart objekt.På grund af det vil jeg springe over alle de andre måder, du kan oprette et objekt på, men jeg er nødt til at nævne, at de fleste af disse eksempler er PowerShell v3.0 og nyere.

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

Denne metode fungerer godt for mig, fordi jeg bruger hashtables til stort set alt. Men der er tidspunkter, hvor jeg gerne vil have PowerShell til at behandle hashtables mere som et objekt. Det første sted, hvor du bemærker forskellen, er, når du vil bruge Format-Table eller Export-CSV, og du indser, at ahashtable blot er en samling af nøgle/værdipar.

Du kan derefter få adgang til og bruge værdierne, som du ville gøre med et normalt objekt.

$myObject.Name

Konvertering af en hashtable

Mens jeg er ved emnet, vidste du så, at du kan gøre dette:

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

Jeg foretrækker at oprette objektet fra starten, men der er tidspunkter, hvor man er nødt til at arbejde med ahashtable først. Dette eksempel virker, fordi konstruktøren tager en hashtabel for objektets egenskaber. En vigtig bemærkning er, at selv om denne metode virker, er det ikke en nøjagtig ækvivalent. Den største forskel er, at rækkefølgen af egenskaberne ikke er bevaret.

Legacy-tilgang

Du har måske set folk bruge New-Object til at oprette brugerdefinerede objekter.

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

Denne måde er en del langsommere, men det kan være din bedste mulighed i tidlige versioner af PowerShell.

Sparring til en fil

Jeg synes, at den bedste måde at gemme en hashtabel til en fil er at gemme den som JSON. Du kan importere den tilbage i en

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

Jeg dækker flere måder at gemme objekter til en fil på i min artikel omDe mange måder at læse og skrive til filer på.

Arbejde med egenskaber

Tilføje egenskaber

Du kan stadig tilføje nye egenskaber til din PSCustomObject med Add-Member.

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

Fjernelse af egenskaber

Du kan også fjerne egenskaber fra et objekt.

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

psobject er en skjult egenskab, der giver dig adgang til metadata for basisobjekter.

Enumerering af egenskabsnavne

Sommetider har du brug for en liste over alle egenskabsnavne på et objekt.

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

Vi kan også få den samme liste fra psobject-egenskaben.

$myobject.psobject.properties.name

Dynamisk adgang til egenskaber

Jeg har allerede nævnt, at du kan få direkte adgang til egenskabsværdier.

$myObject.Name

Du kan bruge en streng til egenskabsnavnet, og det vil stadig fungere.

$myObject.'Name'

Vi kan tage dette et skridt videre og bruge en variabel til egenskabsnavnet.

$property = 'Name'$myObject.$property

Jeg ved godt, at det ser mærkeligt ud, men det virker.

Konverter PSCustomObject til en hashtabel

For at fortsætte fra sidste afsnit kan du dynamisk gennemgå egenskaberne og oprette en hashtabel ud fra dem.

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

Test for egenskaber

Hvis du har brug for at vide, om en egenskab findes, kan du blot kontrollere, om den pågældende egenskab har en værdi.

if( $null -ne $myObject.ID )

Men hvis værdien kunne være $null, kan du kontrollere, om den findes ved at kontrollerepsobject.properties for den.

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

Tilføjelse af objektmetoder

Hvis du har brug for at tilføje en scriptmetode til et objekt, kan du gøre det med Add-Member og enScriptBlock. Du skal bruge den automatiske this-variabel reference til det aktuelle objekt. Her er ascriptblock til at forvandle et objekt til en hashtabel. (samme kode form det sidste eksempel)

Dernæst tilføjer vi den til vores objekt som en script-egenskab.

Så kan vi kalde vores funktion på denne måde:

$myObject.ToHashtable()

Objekter vs. værdityper

Objekter og værdityper håndterer ikke variabeltildelinger på samme måde. Hvis du tildeler værdityper til hinanden, er det kun værdien, der bliver kopieret til den nye variabel.

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

I dette tilfælde er $first 1 og $second 2.

Objektvariabler indeholder en reference til det faktiske objekt. Når du tildeler et objekt til en nyvariabel, refererer de stadig til det samme objekt.

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

Da $third og $fourth refererer til den samme instans af et objekt, er både $third.key og$fourth.Key 4.

psobject.copy()

Hvis du har brug for en ægte kopi af et objekt, kan du klone det.

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

Clone opretter en overfladisk kopi af objektet. De har forskellige instanser nu, og $third.key er 3og $fourth.Key er 4 i dette eksempel.

Jeg kalder dette en overfladisk kopi, fordi hvis du har indlejrede objekter. (hvor egenskaberne indeholder andreobjekter). Det er kun værdierne på øverste niveau, der kopieres. Underobjekterne vil referere til hinanden.

PSTypeName for brugerdefinerede objekttyper

Nu, hvor vi har et objekt, er der et par ting mere, vi kan gøre med det, som måske ikke er nær så indlysende. Det første, vi skal gøre, er at give det en PSTypeName. Dette er den mest almindelige måde jeg ser folk gøre det på:

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

Jeg har for nylig opdaget en anden måde at gøre dette på fra dette indlæg af /u/markekraus. Jeg gjorde en littledigging og flere indlæg om ideen fra Adam Bertram og Mike Shepard, hvor de talkabout denne tilgang, der giver dig mulighed for at definere det inline.

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

Jeg elsker, hvor pænt dette bare passer ind i sproget. Nu hvor vi har et objekt med et korrekt typenavn, kan vi gøre nogle flere ting.

Note

Du kan også oprette brugerdefinerede PowerShell-typer ved hjælp af PowerShell-klasser. Du kan finde flere oplysninger under Oversigt over PowerShell-klasser.

Brug af DefaultPropertySet (den lange vej)

PowerShell bestemmer for os, hvilke egenskaber der skal vises som standard. Mange af de native kommandoer har en.ps1xml formateringsfil, der gør alt det tunge arbejde. Fra dette indlæg af Boe Prox,er der en anden måde for os at gøre dette på vores brugerdefinerede objekt ved hjælp af bare PowerShell. Vi kan give den enMemberSet til den at bruge.

Nu, når mit objekt bare falder til shell, vil den kun vise disse egenskaber som standard.

Update-TypeData with DefaultPropertySet

Dette er rart, men jeg så for nylig en bedre måde, da jeg såPowerShell unplugged 2016 med Jeffrey Snover & Don Jones. Jeffrey brugteUpdate-TypeData til at angive standardegenskaberne.

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

Det er simpelt nok, at jeg næsten kunne huske det, hvis jeg ikke havde dette indlæg som en quickreference. Nu kan jeg nemt oprette objekter med masser af egenskaber og stadig give det et pænt cleanview, når jeg ser på det fra shell’en. Hvis jeg har brug for at få adgang til eller se disse andre egenskaber, er de stadig der.

$myObject | Format-List *

Update-TypeData med ScriptProperty

Det andet, jeg fik ud af denne video, var at oprette script properties til dine objekter. Dette ville være et godt tidspunkt at påpege, at dette også fungerer for eksisterende objekter.

Du kan gøre dette, før dit objekt oprettes eller efter, og det vil stadig fungere. Det er det, der gør dette anderledes end at bruge Add-Member med en script-egenskab. Når du bruger Add-Member på den måde, som jeg henviste til tidligere, eksisterer den kun på den specifikke instans af objektet. Denne gælder for alleobjekter med denne TypeName.

Funktionsparametre

Du kan nu bruge disse brugerdefinerede typer til parametre i dine funktioner og scripts. Du kan få onefunktion til at oprette disse brugerdefinerede objekter og derefter sende dem videre til andre funktioner.

param( $Data )

PowerShell kræver, at objektet er af den type, du har angivet. Den kaster en valideringsfejl, hvis typen ikke passer automatisk for at spare dig for at skulle teste for det i din kode. Et godt eksempel på at lade PowerShell gøre det, den er bedst til.

Funktion OutputType

Du kan også definere en OutputType for dine avancerede funktioner.

function Get-MyObject{ param ( ...

Attributværdien OutputType er kun en dokumentationsnote. Den er ikke afledt af funktionskoden eller sammenlignet med det faktiske funktionsoutput.

Den vigtigste grund til, at du bruger en outputtype, er, at metainformationerne om din funktion afspejler dine intentioner. Ting som Get-Command og Get-Help, som dit udviklingsmiljø kan drage fordel af. Hvis du vil have flere oplysninger, så tag et kig på hjælpen til det: about_Functions_OutputTypeAttribute.

Med det sagt, hvis du bruger Pester til at enhedsteste dine funktioner, så ville det være en god ide at validere outputobjekterne matcher din OutputType. Dette kunne fange variabler, der bare falder i røret, når de ikke burde.

Sluttende tanker

Sammenhængen i dette handlede om , men mange af disse oplysninger gælder forobjekter generelt.

Jeg har set de fleste af disse funktioner i forbifarten før, men aldrig set dem præsenteret som en samling af oplysninger om PSCustomObject. Så sent som i sidste uge faldt jeg over endnu en og blev overrasket over, at jeg ikke havde set den før. Jeg ønskede at samle alle disse idéer, så du forhåbentlig kan se det større billede og være opmærksom på dem, når du får mulighed for at bruge dem. Jeg håber, at du lærer noget og kan finde en måde at indarbejde dette i dine scripts.

Similar Posts

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.