- 10/05/2020
- 8 minut čtení
-
- j
- m
- s
- j
- c
PSCustomObject
s jsou skvělým nástrojem, který můžete přidat do svého opasku nástrojů PowerShell. Začněme se základya propracujme se k pokročilejším funkcím. Myšlenkou použití PSCustomObject
je mít jednoduchý způsob vytváření strukturovaných dat. Podívejte se na první příklad a budete mít lepší představu o tom, co to znamená.
Poznámka
Původní verze tohoto článku se objevila na blogu, jehož autorem je @KevinMarquette. TýmPowerShell děkuje Kevinovi za sdílení tohoto obsahu s námi. Podívejte se prosím na jeho blog na adresePowerShellExplained.com.
- Vytvoření objektu PSCustomObject
- Konverze hashtable
- Přístup podle legendy
- Uložení do souboru
- Práce s vlastnostmi
- Přidávání vlastností
- Odstraňování vlastností
- Vyčíslení názvů vlastností
- Dynamický přístup k vlastnostem
- Převedení PSCustomObject na hashtable
- Testování vlastností
- Přidání metod objektu
- Objekty vs hodnotové typy
- psobject.copy()
- PSTypeName pro vlastní typy objektů
- Použití sady DefaultPropertySet (delší cesta)
- Update-TypeData s DefaultPropertySet
- Update-TypeData with ScriptProperty
- Parametry funkcí
- Funkce OutputType
- Závěrečné myšlenky
Vytvoření objektu PSCustomObject
Mám rád používání v prostředí PowerShell. Vytvoření použitelného objektu nebylo nikdy jednodušší. z tohoto důvodu přeskočím všechny ostatní způsoby, jak můžete objekt vytvořit, ale musím zmínit, že většina těchto příkladů je pro PowerShell v3.0 a novější.
$myObject = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
Tento způsob mi vyhovuje, protože hashtables používám téměř na všechno. Ale jsou chvíle, kdy bych chtěl, aby PowerShell zacházel s hashtables více jako s objektem. Prvním místem, kde si všimnete rozdílu, je, když chcete použít Format-Table
nebo Export-CSV
a uvědomíte si, že hashtable je jen kolekce dvojic klíč/hodnota.
K hodnotám pak můžete přistupovat a používat je jako u běžného objektu.
$myObject.Name
Konverze hashtable
Když už jsem u toho, věděli jste, že můžete udělat toto:
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = $myHashtable
Přednostně vytvářím objekt od začátku, ale jsou chvíle, kdy je třeba s ahashtable nejprve pracovat. Tento příklad funguje, protože konstruktor přebírá hashtable pro objektvlastnosti. Důležitá poznámka je, že tato metoda sice funguje, ale není přesným ekvivalentem. Největší rozdíl je v tom, že není zachováno pořadí vlastností.
Přístup podle legendy
Možná jste viděli, že lidé používají New-Object
k vytváření vlastních objektů.
$myHashtable = @{ Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}$myObject = New-Object -TypeName PSObject -Property $myHashtable
Tento způsob je o dost pomalejší, ale v raných verzích prostředí PowerShell to může být nejlepší volba.
Uložení do souboru
Zjistil jsem, že nejlepší způsob, jak uložit hashtable do souboru, je uložit jej jako JSON. Můžete jej importovat zpět do
$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path$myObject = Get-Content -Path $Path | ConvertFrom-Json
Dalším způsobům ukládání objektů do souboru se věnuji v článku Mnoho způsobů čtení a zápisu do souborů.
Práce s vlastnostmi
Přidávání vlastností
Stále můžete přidávat nové vlastnosti do svého PSCustomObject
pomocí Add-Member
.
$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'$myObject.ID
Odstraňování vlastností
Můžete také odebrat vlastnosti z objektu.
$myObject.psobject.properties.remove('ID')
Vlastnost psobject
je skrytá vlastnost, která vám umožňuje přístup k metadatům základního objektu.
Vyčíslení názvů vlastností
Někdy potřebujete seznam všech názvů vlastností objektu.
$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name
Tentýž seznam můžeme získat i z vlastnosti psobject
.
$myobject.psobject.properties.name
Dynamický přístup k vlastnostem
Již jsem se zmínil, že k hodnotám vlastností můžete přistupovat přímo.
$myObject.Name
Můžete pro název vlastnosti použít řetězec a bude to stále fungovat.
$myObject.'Name'
Můžeme udělat ještě jeden krok a pro název vlastnosti použít proměnnou.
$property = 'Name'$myObject.$property
Vím, že to vypadá divně, ale funguje to.
Převedení PSCustomObject na hashtable
Pokračovat z minulé části můžete dynamicky procházet vlastnosti a vytvořit z nich hashtable.
$hashtable = @{}foreach( $property in $myobject.psobject.properties.name ){ $hashtable = $myObject.$property}
Testování vlastností
Pokud potřebujete zjistit, zda nějaká vlastnost existuje, můžete prostě zkontrolovat, zda má daná vlastnost hodnotu.
if( $null -ne $myObject.ID )
Pokud by ale hodnota mohla být $null
, můžete zkontrolovat, zda existuje, tak, že pro ni zkontrolujetepsobject.properties
.
if( $myobject.psobject.properties.match('ID').Count )
Přidání metod objektu
Pokud potřebujete přidat metodu skriptu k objektu, můžete to udělat pomocí Add-Member
aScriptBlock
. Musíte použít automatickou proměnnou this
odkaz na aktuální objekt. Zde je ascriptblock
pro přeměnu objektu na hashtable. (stejný kód jako v minulém příkladu)
Poté ji přidáme do našeho objektu jako vlastnost skriptu.
Poté můžeme zavolat naši funkci takto:
$myObject.ToHashtable()
Objekty vs hodnotové typy
Objekty a hodnotové typy nezpracovávají přiřazení proměnných stejným způsobem. Při přiřazení hodnotových typů se do nové proměnné zkopíruje pouze hodnota.
$first = 1$second = $first$second = 2
V tomto případě je $first
1 a $second
2.
Objektové proměnné uchovávají odkaz na skutečný objekt. Když přiřadíte jeden objekt nové proměnné, stále odkazují na stejný objekt.
$third = @{Key=3}$fourth = $third$fourth.Key = 4
Protože $third
a $fourth
odkazují na stejnou instanci objektu, jsou $third.key
i$fourth.Key
4.
psobject.copy()
Potřebujete-li skutečnou kopii objektu, můžete jej klonovat.
$third = @{Key=3}$fourth = $third.psobject.copy()$fourth.Key = 4
Klonování vytvoří mělkou kopii objektu. Nyní mají různé instance a $third.key
je 3a $fourth.Key
je 4 v tomto příkladu.
Říkám tomu mělká kopie, protože pokud máte vnořené objekty. (kde vlastnosti obsahují jinéobjekty). Kopírují se pouze hodnoty nejvyšší úrovně. Podřízené objekty budou odkazovat jeden na druhý.
PSTypeName pro vlastní typy objektů
Teď, když máme objekt, můžeme s ním dělat ještě několik věcí, které nemusí být zdaleka tak zřejmé. První věc, kterou musíme udělat, je dát mu PSTypeName
. Tohle je nejčastější způsob, který vídám, jak to lidé dělají:
$myObject.PSObject.TypeNames.Insert(0,"My.Object")
Nedávno jsem objevil další způsob, jak to udělat z tohoto příspěvku od /u/markekraus. Trochu jsem zapátral a našel jsem další příspěvky o nápadu od Adama Bertrama a Mikea Sheparda, kde se mluví o tomto přístupu, který umožňuje definovat to inline.
$myObject = @{ PSTypeName = 'My.Object' Name = 'Kevin' Language = 'PowerShell' State = 'Texas'}
Líbí se mi, jak pěkně to prostě zapadá do jazyka. Nyní, když máme objekt se správným typename, můžeme dělat další věci.
Poznámka
Vlastní typy prostředí PowerShell můžete vytvářet také pomocí tříd prostředí PowerShell. Další informace naleznete v částiPřehled tříd prostředí PowerShell.
Použití sady DefaultPropertySet (delší cesta)
PowerShell za nás rozhodne, jaké vlastnosti se mají zobrazit ve výchozím nastavení. Mnoho nativních příkazů má .ps1xml
formátovací soubor, který dělá všechnu těžkou práci. Z tohoto příspěvku od Boe Prox,existuje další způsob, jak to můžeme udělat na našem vlastním objektu pouze pomocí PowerShellu. Můžeme mu zadatMemberSet
, aby se použil.
Nyní, když můj objekt prostě spadne do shellu, bude ve výchozím nastavení zobrazovat jen tyto vlastnosti.
Update-TypeData s DefaultPropertySet
To je pěkné, ale nedávno jsem viděl lepší způsob, když jsem sledovalPowerShell unplugged 2016 s Jeffrey Snoverem & Donem Jonesem. Jeffrey používalUpdate-TypeData pro zadání výchozích vlastností.
$TypeData = @{ TypeName = 'My.Object' DefaultDisplayPropertySet = 'Name','Language'}Update-TypeData @TypeData
To je natolik jednoduché, že bych si to skoro pamatoval, kdybych neměl tento příspěvek jako rychlý odkaz. Nyní mohu snadno vytvářet objekty se spoustou vlastností a přitom jim dát při pohledu ze shellu pěkně čistý vzhled. Pokud potřebuji přistupovat k těmto dalším vlastnostem nebo je vidět, jsou tam stále.
$myObject | Format-List *
Update-TypeData with ScriptProperty
Něco dalšího, co jsem si z tohoto videa odnesl, bylo vytváření skriptových vlastností pro vaše objekty. Tentokrát by bylo dobré upozornit, že to funguje i pro existující objekty.
Můžete to udělat před vytvořením objektu nebo po něm a bude to stále fungovat. Tím se to liší od použití Add-Member
s vlastností skriptu. Když použijete Add-Member
dříve uvedeným způsobem, existuje pouze na této konkrétní instanci objektu. Tato se vztahuje na všechnyobjekty s touto TypeName
.
Parametry funkcí
Tyto vlastní typy můžete nyní používat pro parametry ve svých funkcích a skriptech. Můžete nechat jednu funkci vytvořit tyto vlastní objekty a pak je předávat do dalších funkcí.
param( $Data )
PowerShell vyžaduje, aby objekt byl zadaného typu. Pokud typ neodpovídá, automaticky vyhodí chybu ověření, aby vám ušetřil krok testování tohoto typu v kódu. Skvělýpříklad toho, jak nechat PowerShell dělat to, co umí nejlépe.
Funkce OutputType
Můžete také definovat OutputType
pro své pokročilé funkce.
function Get-MyObject{ param ( ...
Hodnota atributu OutputType je pouze dokumentační poznámka. Není odvozena z kódu funkce ani není porovnávána se skutečným výstupem funkce.
Hlavním důvodem, proč byste měli použít typ výstupu, je, aby metainformace o vaší funkciodrážely vaše záměry. Věci jako Get-Command
a Get-Help
, které vaše vývojové prostředímůže využít. Pokud chcete více informací, pak se podívejte do nápovědy k němu:about_Functions_OutputTypeAttribute.
Pokud používáte Pester k unit testování svých funkcí, pak by bylo dobré ověřit, zda výstupní objekty odpovídají vašemu OutputType. To by mohlo zachytit proměnné, které prostě spadnou do roury, i když by neměly.
Závěrečné myšlenky
Kontext tohoto článku se týkal , ale mnoho z těchto informací platí pro objekty obecně.
Většinu těchto funkcí jsem již dříve letmo viděl, ale nikdy jsem je neviděl prezentované jako souborinformací o PSCustomObject
. Zrovna minulý týden jsem narazil na další a byl jsem překvapen,že jsem ji předtím neviděl. Chtěl jsem všechny tyto myšlenky shromáždit, abyste snad viděli širší souvislosti a uvědomili si je, až budete mít příležitost je použít. Doufám, že se něco naučíte a najdete způsob, jak je zapracovat do svých skriptů.