Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
PSCustomObject
to doskonałe narzędzie do dodania do pasa narzędzi programu PowerShell. Zacznijmy od podstaw i przyjrzyjmy się bardziej zaawansowanym funkcjom. Chodzi o to PSCustomObject
, aby utworzyć dane ustrukturyzowane w prosty sposób. Przyjrzyj się pierwszem przykładom i lepiej zrozumiesz, co to oznacza.
Uwaga
Oryginalna wersja tego artykułu pojawiła się na blogu prowadzonym przez @KevinMarquette. Zespół programu PowerShell dziękuje Kevinowi za udostępnienie tej zawartości nam. Zapoznaj się ze swoim blogiem na PowerShellExplained.com.
Tworzenie obiektu PSCustomObject
Uwielbiam używać [pscustomobject]
w programie PowerShell. Tworzenie obiektu użytecznego nigdy nie było łatwiejsze.
W związku z tym zamierzam pominąć wszystkie inne sposoby tworzenia obiektu, ale muszę wspomnieć, że większość z tych przykładów to program PowerShell w wersji 3.0 i nowszej.
$myObject = [pscustomobject]@{
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
Ta metoda działa dobrze dla mnie, ponieważ używam tabel skrótów dla prawie wszystkiego. Ale czasami chciałbym, aby program PowerShell traktować tabele skrótów bardziej jak obiekt. Pierwsze miejsce, w którym zauważysz różnicę, jest to, że chcesz użyć Format-Table
metody lub Export-Csv
i zdajesz sobie sprawę, że tabela skrótu to tylko kolekcja par klucz/wartość.
Następnie możesz uzyskać dostęp do tych wartości i użyć tych wartości, jak zwykły obiekt.
$myObject.Name
Konwertowanie tabeli skrótu
Chociaż jestem na ten temat, czy wiesz, że możesz to zrobić:
$myHashtable = @{
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
$myObject = [pscustomobject]$myHashtable
Wolę utworzyć obiekt od zera, ale czasami trzeba najpierw pracować z tabelą skrótu. Ten przykład działa, ponieważ konstruktor przyjmuje tablicę skrótów jako właściwości obiektu. Jedną z ważnych uwag jest to, że chociaż ta metoda działa, nie jest to dokładne odpowiedniki. Największą różnicą jest to, że kolejność właściwości nie jest zachowywana.
Jeśli chcesz zachować kolejność, zobacz Uporządkowane tabele skrótów.
Przestarzałe podejście
Być może widziałeś ludzi używających New-Object
do tworzenia obiektów niestandardowych.
$myHashtable = @{
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
$myObject = New-Object -TypeName psobject -Property $myHashtable
W ten sposób jest to nieco wolniejsze, ale może to być najlepsza opcja we wczesnych wersjach programu PowerShell.
Zapisywanie do pliku
Uważam, że najlepszym sposobem zapisania tabeli skrótu w pliku jest zapisanie go w formacie JSON. Możesz zaimportować go z powrotem do [pscustomobject]
$myObject | ConvertTo-Json -Depth 1 | Set-Content -Path $Path
$myObject = Get-Content -Path $Path | ConvertFrom-Json
Opisuję więcej sposobów zapisywania obiektów w pliku w moim artykule na wiele sposobów odczytywania i zapisywania w plikach.
Praca z właściwościami
Dodawanie właściwości
Możesz nadal dodawać nowe właściwości do pliku PSCustomObject
za pomocą polecenia Add-Member
.
$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'
$myObject.ID
Usuń właściwości
Można również usunąć właściwości z obiektu.
$myObject.psobject.Properties.Remove('ID')
Element .psobject
jest elementem wewnętrznym, który zapewnia dostęp do metadanych obiektu podstawowego. Aby uzyskać więcej informacji na temat elementów wewnętrznych, zobacz about_Intrinsic_Members.
Wyliczanie nazw właściwości
Czasami potrzebna jest lista wszystkich nazw właściwości obiektu.
$myObject | Get-Member -MemberType NoteProperty | select -ExpandProperty Name
Możemy pobrać tę samą listę również z właściwości psobject
.
$myobject.psobject.Properties.Name
Uwaga
Get-Member
Zwraca właściwości w kolejności alfabetycznej. Użycie operatora dostępu do elementów, aby wypisać nazwy właściwości, zwraca je w kolejności, w jakiej były definiowane w obiekcie.
Dynamiczne uzyskiwanie dostępu do właściwości
Już wspomniałem, że można uzyskać bezpośredni dostęp do wartości właściwości.
$myObject.Name
Możesz użyć ciągu dla nazwy właściwości i nadal będzie działać.
$myObject.'Name'
Możemy wykonać ten jeszcze jeden krok i użyć zmiennej dla nazwy właściwości.
$property = 'Name'
$myObject.$property
Wiem, że wygląda dziwnie, ale to działa.
Konwertowanie obiektu PSCustomObject na tabelę skrótów
Aby kontynuować pracę z ostatniej sekcji, możesz dynamicznie przechodzić przez właściwości i tworzyć z nich tabelę skrótów.
$hashtable = @{}
foreach( $property in $myobject.psobject.Properties.Name )
{
$hashtable[$property] = $myObject.$property
}
Testowanie właściwości
Jeśli musisz wiedzieć, czy właściwość istnieje, możesz po prostu sprawdzić, czy ta właściwość ma wartość.
if( $null -ne $myObject.ID )
Jeśli jednak wartość może być $null
, możesz sprawdzić, czy istnieje, sprawdzając psobject.Properties
.
if( $myobject.psobject.Properties.Match('ID').Count )
Dodawanie metod obiektów
Jeśli musisz dodać metodę skryptu do obiektu, możesz to zrobić za pomocą Add-Member
i ScriptBlock
. Aby odwołać się do bieżącego obiektu, należy użyć automatycznej zmiennej this
. Oto element scriptblock
umożliwiający przekształcenie obiektu w tabelę skrótów. (ten sam kod w ostatnim przykładzie)
$ScriptBlock = {
$hashtable = @{}
foreach( $property in $this.psobject.Properties.Name )
{
$hashtable[$property] = $this.$property
}
return $hashtable
}
Następnie dodamy go do naszego obiektu jako właściwość skryptu.
$memberParam = @{
MemberType = "ScriptMethod"
InputObject = $myobject
Name = "ToHashtable"
Value = $scriptBlock
}
Add-Member @memberParam
Następnie możemy wywołać naszą funkcję w następujący sposób:
$myObject.ToHashtable()
Obiekty a typy wartości
Obiekty i typy wartości nie obsługują przypisań zmiennych w taki sam sposób. W przypadku przypisania typów wartości do siebie tylko wartość zostanie skopiowana do nowej zmiennej.
$first = 1
$second = $first
$second = 2
W tym przypadku $first
wartość to 1 i $second
ma wartość 2.
Zmienne obiektu przechowują odwołanie do rzeczywistego obiektu. Po przypisaniu jednego obiektu do nowej zmiennej nadal odwołują się do tego samego obiektu.
$third = [pscustomobject]@{Key=3}
$fourth = $third
$fourth.Key = 4
Ponieważ $third
i $fourth
odwołuje się do tego samego wystąpienia obiektu, oba $third.key
i $fourth.Key
mają wartość 4.
psobject. Copy()
Jeśli potrzebujesz prawdziwej kopii obiektu, możesz go sklonować.
$third = [pscustomobject]@{Key=3}
$fourth = $third.psobject.Copy()
$fourth.Key = 4
Klon tworzy płytkią kopię obiektu. Mają teraz różne wystąpienia i $third.key
mają wartość 3 i $fourth.Key
ma wartość 4 w tym przykładzie.
Nazywam to płytką kopią, ponieważ jeśli istnieją zagnieżdżone obiekty (to jest obiekty, których właściwości zawierają inne obiekty), kopiowane są tylko wartości najwyższego poziomu. Obiekty podrzędne będą się odwoływać do siebie.
PSTypeName dla typów obiektów niestandardowych
Teraz, gdy mamy obiekt, istnieje kilka innych rzeczy, które możemy z tym zrobić, które mogą nie być prawie tak oczywiste. Pierwszą rzeczą, którą musimy zrobić, jest nadanie mu PSTypeName
. Jest to najbardziej typowy sposób, w jaki widzę, że ludzie to robią:
$myObject.psobject.TypeNames.Insert(0,"My.Object")
Niedawno odkryłem inny sposób, aby to zrobić z Redditor u/markekraus
. Mówi o tym podejściu, które umożliwia zdefiniowanie go w tekście.
$myObject = [pscustomobject]@{
PSTypeName = 'My.Object'
Name = 'Kevin'
Language = 'PowerShell'
State = 'Texas'
}
Uwielbiam, jak miło to po prostu pasuje do języka. Teraz, gdy mamy obiekt o odpowiedniej nazwie typu, możemy wykonać kilka innych czynności.
Uwaga
Można również tworzyć niestandardowe typy programu PowerShell przy użyciu klas programu PowerShell. Aby uzyskać więcej informacji, zobacz Omówienie klasy programu PowerShell.
Korzystanie z elementu DefaultPropertySet (długa droga)
Program PowerShell decyduje o tym, jakie właściwości mają być wyświetlane domyślnie. Wiele poleceń natywnych ma .ps1xml
plik formatowania, który wykonuje wszystkie złożone zadania. W tym wpisie Boe Prox znajdujemy inny sposób, aby wykonać to na naszym obiekcie niestandardowym, używając tylko PowerShell. Możemy dać MemberSet
, aby mogła go użyć.
$defaultDisplaySet = 'Name','Language'
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
$MyObject | Add-Member MemberSet PSStandardMembers $PSStandardMembers
Teraz, gdy mój obiekt opadnie na powłokę, domyślnie będzie pokazywał tylko te właściwości.
Update-TypeData z ustawieniem DefaultPropertySet
Jest to miłe, ale ostatnio widziałem lepszy sposób używania update-TypeData do określenia właściwości domyślnych.
$TypeData = @{
TypeName = 'My.Object'
DefaultDisplayPropertySet = 'Name','Language'
}
Update-TypeData @TypeData
To jest na tyle proste, że gdybym nie miał tego postu jako szybkiego odniesienia, mógłbym to prawie zapamiętać. Teraz mogę łatwo tworzyć obiekty z dużą ilością właściwości, a jednocześnie nadać im ładny i przejrzysty widok podczas przeglądania ich z powłoki. Jeśli muszę uzyskać dostęp do tych innych właściwości lub zobaczyć je, nadal są tam.
$myObject | Format-List *
Update-TypeData z użyciem właściwości ScriptProperty
Coś jeszcze, co wyniosłem z tego filmu, to tworzenie właściwości skryptu dla twoich obiektów. Byłoby to dobry moment, aby wskazać, że działa to również dla istniejących obiektów.
$TypeData = @{
TypeName = 'My.Object'
MemberType = 'ScriptProperty'
MemberName = 'UpperCaseName'
Value = {$this.Name.ToUpper()}
}
Update-TypeData @TypeData
Można to zrobić przed utworzeniem obiektu lub po nim i nadal będzie działać. To sprawia, że różni się to od użycia Add-Member
z właściwością skryptu. Jeśli używasz Add-Member
w sposób, do którego odnosiłem się wcześniej, istnieje on tylko w tym konkretnym wystąpieniu obiektu. Dotyczy to wszystkich obiektów z tym TypeName
elementem .
Parametry funkcji
Możesz teraz używać tych typów niestandardowych dla parametrów w funkcjach i skryptach. Możesz mieć jedną funkcję tworzącą te niestandardowe obiekty i następnie przekazać je do innych funkcji.
param( [PSTypeName('My.Object')]$Data )
Program PowerShell wymaga, aby obiekt był określonym typem. Zgłasza błąd weryfikacji, jeśli typ nie jest zgodny automatycznie, aby zaoszczędzić ci krok testowania tego w twoim kodzie. Doskonałym przykładem umożliwienia programowi PowerShell zrobienia tego, co robi najlepiej.
Typ wyjściowy funkcji
Można również zdefiniować element OutputType
dla funkcji zaawansowanych.
function Get-MyObject
{
[OutputType('My.Object')]
[CmdletBinding()]
param
(
...
Wartość atrybutu OutputType jest tylko notatką dotyczącą dokumentacji. Nie pochodzi on z kodu funkcji ani nie jest porównywany z rzeczywistymi danymi wyjściowymi funkcji.
Głównym powodem użycia typu danych wyjściowych jest to, że metadane dotyczące funkcji odzwierciedlają intencje. Takie elementy jak Get-Command
i Get-Help
, z których może korzystać środowisko deweloperskie. Jeśli chcesz uzyskać więcej informacji, zapoznaj się z pomocą: about_Functions_OutputTypeAttribute.
Jeśli używasz platformy Pester do testowania swoich funkcji, dobrym pomysłem byłoby sprawdzenie, czy obiekty wyjściowe są zgodne z parametrem OutputType. Może to wychwytywać zmienne, które nie powinny trafiać do potoku.
Myśli zamykające
Kontekstem tego wszystkiego był [pscustomobject]
, ale wiele z tych informacji dotyczy ogólnie obiektów.
Widziałem większość tych funkcji przelotnie wcześniej, ale nigdy nie widziałem ich przedstawionych jako zbiór informacji na PSCustomObject
. Tylko w tym zeszłym tygodniu natknąłem się na innego i był zaskoczony, że nie widziałem go wcześniej. Chciałem wyciągnąć wszystkie te pomysły razem, aby mieć nadzieję, że zobaczysz większy obraz i być świadomy ich, gdy masz okazję ich używać. Mam nadzieję, że czegoś się nauczyłeś i znajdziesz sposób na to, aby zastosować to w swoich skryptach.