
Jakiś czas temu przybliżyłem pojęcie potoku w PowerShell, aby świadomie i sprawnie wykorzystywać funkcjonalność przekazywania wartości pomiędzy poleceniami.
Tym razem chciałbym pójść krok dalej i pokazać, które elementy musisz zastosować we własnych funkcjach, aby również wspierały pobieranie wartości z potoku.
Akceptowanie danych z potoku
Dodaj atrybut ValueFromPipeline lub ValueFromPipelineByPropertyName do parametru, który ma akceptować dane wejściowe z potoku.
- wybierz
ValueFromPipelineByPropertyName
(metoda ByPropertyName), jeśli chcesz przekazywać konkretną właściwość obiektu. Funkcja możesz zawierać kilka parametrów właśnie z takim atrybutem.
function Get-SystemVersion { [PSCustomObject]@{ Version = 41 System = 'SystemX' } } function Update-SystemVersion { param( [Parameter(ValueFromPipelineByPropertyName)] $Version, [Parameter(ValueFromPipelineByPropertyName)] $System ) $Version + 1 $System } Get-SystemVersion | Update-SystemVersion
Zobacz na przykładzie, właściwości obiektu z funkcji Get-SystemVersion mają takie same nazwy jak parametry funkcji Update-SystemVersion. To pozwoliło na przekazanie wartości poprzez potok.
Pamiętaj, aby przekazanie zadziałało, wymagana jest zgodność nazw właściwości i parametrów.

- wybierz
ValueFromPipeline
(metoda ByValue) , jeśli wolisz przekazać za pomocą jednego parametru cały obiekt. W natywnych cmdletach często można zauważyć wykorzystywane w tym celu parametr -InputObject.
function Get-SystemVersion { [PSCustomObject]@{ Version = 41 System = 'SystemX' } } function Update-SystemVersion { param( [Parameter(ValueFromPipeline)] $InputObject ) $InputObject.Version + 1 $InputObject.System } Get-SystemVersion | Update-SystemVersion
Zmiana atrybut na ValueFromPipeline, wymusiło zmodyfikowanie funkcji Update-SystemVersion . Teraz pracujemy z całym obiektem, zamiast z wartościami w zmiennych (i mamy w ten sposób dostęp do nadmiarowych danych).

Po przykładach mogłoby się wydawać, że to wszystko, co potrzebujemy zrobić. Funkcje działają, dane są przekazyane. Jednak nie do końca…
Blok Process
Jeśli któryś z parametrów funkcji jest ustawiony na akceptowanie danych wejściowych potoku, a blok Process
nie jest zdefiniowany, przetwarzanie rekord po rekordzie zakończy się niepowodzeniem.

W takim przypadku funkcja wykona się tylko raz, niezależnie od ilości danych na wyjściu poprzedniej funkcji.
Dlatego konieczne jest dodanie bloku Process
, która spowoduję poprawnie przetwarzanie danych przekazywanych w potoku.

function Get-SystemVersion { [PSCustomObject]@{ Version = 41 System = 'SystemX' } [PSCustomObject]@{ Version = 31 System = 'SystemY' } } function Update-SystemVersion { param( [Parameter(ValueFromPipeline)] $InputObject ) process { $InputObject.Version + 1 $InputObject.System } } Get-SystemVersion | Update-SystemVersion
Z Process
związane są jeszcze bloki End
oraz Begin
, które nie są wymagane, lecz niekiedy mogą okazać się przydatne. Będą to miejsca, gdzie wykonamy coś raz na początku i na końcu przetwarzania potoku.
Po więcej informacji odsyłam do dokumentacji.
Podsumowanie
Wystarczy tylko tyle, aby własne funkcje potrafiły przekazywać dane poprzez potok. Należy pamiętać o dwóch sprawach, odpowiednim atrybucie dla parametru/parametrów oraz bloku Process
, który jest niezbędny do przetwarzania każdego rekordu.
Nie zapomnij również o odpowiedniej walidacji parametrów i sprawdzanie „przychodzących” wartości/obiektów do funkcji. Zwracam na to uwagę, mimo że to sprawa, o którą należy dbać niezależnie od tego, czy wykorzystujemy przekazywanie potokiem, czy nie.
No comments yet.