Allt du ville veta om PSCustomObject

author
9 minutes, 11 seconds Read
  • 10/05/2020
  • 8 minuter att läsa
    • j
    • m
    • s
    • j
    • c

PSCustomObjects är ett utmärkt verktyg att lägga till i ditt PowerShell-verktygsbälte. Vi börjar med grunderna och arbetar oss fram till de mer avancerade funktionerna. Tanken bakom att använda en PSCustomObject är att ha ett enkelt sätt att skapa strukturerade data. Ta en titt på det första exemplet så får du en bättre uppfattning om vad det innebär.

Note

Originalversionen av den här artikeln publicerades på bloggen skriven av @KevinMarquette. PowerShell-teamet tackar Kevin för att han delade detta innehåll med oss. Kolla gärna in hans blogg påPowerShellExplained.com.

Skapa ett PSCustomObject

Jag älskar att använda i PowerShell. Att skapa ett användbart objekt har aldrig varit enklare.På grund av detta kommer jag att hoppa över alla andra sätt du kan skapa ett objekt, men jag måste nämna att de flesta av dessa exempel är PowerShell v3.0 och nyare.

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

Denna metod fungerar bra för mig eftersom jag använder hashtables för nästan allt. Men det finns tillfällen då jag skulle vilja att PowerShell behandlar hashtables mer som ett objekt. Det första stället där du märker skillnaden är när du vill använda Format-Table eller Export-CSV och du inser att ahashtable bara är en samling nyckel/värdepar.

Du kan då komma åt och använda värdena som du skulle göra med ett vanligt objekt.

$myObject.Name

Konvertering av en hashtable

När jag ändå är inne på ämnet, visste du att du kan göra så här:

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

Jag föredrar att skapa objektet från början, men det finns tillfällen då man måste arbeta med ahashtable först. Det här exemplet fungerar eftersom konstruktören tar en hashtable för objektets egenskaper. En viktig notering är att även om den här metoden fungerar är den inte en exakt motsvarighet. Den största skillnaden är att egenskapens ordning inte bevaras.

Legacy approach

Du kanske har sett folk använda New-Object för att skapa egna objekt.

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

Detta sätt är ganska mycket långsammare, men det kan vara ditt bästa alternativ i tidiga versioner av PowerShell.

Spara till en fil

Jag tycker att det bästa sättet att spara en hashtable till en fil är att spara den som JSON. Du kan importera den tillbaka till en

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

Jag täcker fler sätt att spara objekt till en fil i min artikel omDe många sätten att läsa och skriva till filer.

Arbeta med egenskaper

Lägga till egenskaper

Du kan fortfarande lägga till nya egenskaper till din PSCustomObject med Add-Member.

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

Ta bort egenskaper

Du kan också ta bort egenskaper från ett objekt.

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

psobject är en dold egenskap som ger dig tillgång till metadata för basobjektet.

Enumerera egenskapsnamn

Ibland behöver du en lista över alla egenskapsnamn på ett objekt.

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

Vi kan få samma lista från egenskapen psobject också.

$myobject.psobject.properties.name

Dynamisk åtkomst till egenskaper

Jag har redan nämnt att du kan få direkt åtkomst till egenskapsvärden.

$myObject.Name

Du kan använda en sträng för egenskapsnamnet och det kommer fortfarande att fungera.

$myObject.'Name'

Vi kan ta detta ett steg till och använda en variabel för egenskapsnamnet.

$property = 'Name'$myObject.$property

Jag vet att det ser konstigt ut, men det fungerar.

Konvertera PSCustomObject till en hashtable

För att fortsätta från förra avsnittet kan du dynamiskt gå igenom egenskaperna och skapa en hashtable från dem.

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

Testa efter egenskaper

Om du behöver veta om en egenskap existerar kan du bara kontrollera om egenskapen har ett värde.

if( $null -ne $myObject.ID )

Men om värdet skulle kunna vara $null kan du kontrollera om den finns genom att kontrollerapsobject.properties för den.

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

Lägga till objektmetoder

Om du behöver lägga till en skriptmetod till ett objekt kan du göra det med Add-Member och enScriptBlock. Du måste använda den automatiska variabeln this som refererar till det aktuella objektet. Här finns ascriptblock för att förvandla ett objekt till en hashtable. (samma kod som i det senaste exemplet)

Därefter lägger vi till den i vårt objekt som en skriptegenskap.

Därefter kan vi anropa vår funktion så här:

$myObject.ToHashtable()

Objekt vs. värdetyper

Objekt och värdetyper hanterar inte variabeltilldelningar på samma sätt. Om du tilldelar värdetyper till varandra kopieras endast värdet till den nya variabeln.

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

I det här fallet är $first 1 och $second 2.

Objektsvariabler innehåller en referens till det faktiska objektet. När du tilldelar ett objekt till en nyvariabel refererar de fortfarande till samma objekt.

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

Om $third och $fourth refererar till samma instans av ett objekt är både $third.key och$fourth.Key 4.

psobject.copy()

Om du behöver en äkta kopia av ett objekt kan du klona det.

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

Clone skapar en ytlig kopia av objektet. De har olika instanser nu och $third.key är 3och $fourth.Key är 4 i det här exemplet.

Jag kallar detta för en ytlig kopia eftersom om du har inbäddade objekt. (där egenskaperna innehåller andra objekt). Endast värdena på den översta nivån kopieras. Barnobjekten refererar till varandra.

PSTypeName för anpassade objekttyper

När vi nu har ett objekt finns det ytterligare några saker vi kan göra med det som kanske inte är lika uppenbara. Det första vi behöver göra är att ge det en PSTypeName. Detta är det vanligaste sättet jag ser folk göra det på:

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

Jag upptäckte nyligen ett annat sätt att göra detta från detta inlägg av /u/markekraus. Jag gjorde en liten sökning och fler inlägg om idén från Adam Bertram och Mike Shepard där de talar om detta tillvägagångssätt som gör att du kan definiera det inline.

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

Jag älskar hur fint detta passar in i språket. Nu när vi har ett objekt med ett korrekt typnamn kan vi göra några fler saker.

Note

Du kan också skapa egna PowerShell-typer med hjälp av PowerShell-klasser. Mer information finns iPowerShell Class Overview.

Using DefaultPropertySet (the long way)

PowerShell bestämmer åt oss vilka egenskaper som ska visas som standard. Många av de inhemska kommandona har en.ps1xml formateringsfil som gör allt det tunga jobbet. Från det här inlägget av Boe Prox finns det ett annat sätt för oss att göra detta på vårt anpassade objekt genom att bara använda PowerShell. Vi kan ge det enMemberSet som det ska använda.

Nu när mitt objekt bara faller till skalet kommer det bara att visa dessa egenskaper som standard.

Update-TypeData with DefaultPropertySet

Detta är trevligt men jag såg nyligen ett bättre sätt när jag tittade påPowerShell unplugged 2016 med Jeffrey Snover & Don Jones. Jeffrey användeUpdate-TypeData för att ange standardegenskaperna.

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

Det är tillräckligt enkelt för att jag nästan skulle kunna komma ihåg det om jag inte hade det här inlägget som en snabbreferens. Nu kan jag enkelt skapa objekt med många egenskaper och ändå ge det en snygg ren bild när jag tittar på det från skalet. Om jag behöver komma åt eller se de andra egenskaperna finns de fortfarande där.

$myObject | Format-List *

Update-TypeData with ScriptProperty

En annan sak som jag fick ut av den videon var att skapa skriptegenskaper för dina objekt. Det här är ett bra tillfälle att påpeka att detta även fungerar för befintliga objekt.

Du kan göra detta innan objektet skapas eller efteråt och det kommer fortfarande att fungera. Det är detta som skiljer detta från att använda Add-Member med en skriptegenskap. När du använder Add-Member på det sätt som jag hänvisade till tidigare finns det bara på den specifika instansen av objektet. Den här gäller för alla objekt med denna TypeName.

Funktionsparametrar

Du kan nu använda dessa anpassade typer för parametrar i dina funktioner och skript. Du kan låta onefunktion skapa dessa anpassade objekt och sedan skicka dem till andra funktioner.

param( $Data )

PowerShell kräver att objektet är av den typ du angett. Ett valideringsfel visas automatiskt om typen inte stämmer överens för att du inte ska behöva testa det i din kod. Ett bra exempel på att låta PowerShell göra det den är bäst på.

Function OutputType

Du kan också definiera ett OutputType för dina avancerade funktioner.

function Get-MyObject{ param ( ...

Värdet för attributet OutputType är bara en dokumentationsanteckning. Det härleds inte från funktionskoden och jämförs inte med den faktiska funktionsutgången.

Den främsta anledningen till att du använder en utdatatyp är att metainformationen om din funktion återspeglar dina avsikter. Saker som Get-Command och Get-Help som din utvecklingsmiljö kan dra nytta av. Om du vill ha mer information kan du ta en titt på hjälpen för det: about_Functions_OutputTypeAttribute.

Med det sagt, om du använder Pester för att enhetstesta dina funktioner så skulle det vara en bra idé att validera att utdataobjekten matchar din OutputType. Detta skulle kunna fånga upp variabler som bara hamnar i röret när de inte borde göra det.

Avslutande tankar

Sammanhanget av detta handlade om , men mycket av den här informationen gäller för objekt i allmänhet.

Jag har sett de flesta av de här funktionerna i förbigående tidigare, men jag har aldrig sett dem presenterade som en samling av information om PSCustomObject. Så sent som förra veckan snubblade jag över ytterligare en och blev förvånad över att jag inte hade sett den tidigare. Jag ville samla alla dessa idéer så att ni förhoppningsvis kan se helheten och bli medvetna om dem när ni har möjlighet att använda dem. Jag hoppas att ni har lärt er något och kan hitta ett sätt att arbeta in detta i era manus.

Similar Posts

Lämna ett svar

Din e-postadress kommer inte publiceras.