Funkcje PowerShell
W tym odcinku serii Ucz się PowerShell przyjrzymy się funkcjom PowerShell. W ostatnim odcinku zajmowaliśmy się skryptami PowerShell, gdzie zaczęliśmy tworzyć rozwiązania i rozwiązywać problemy za pomocą PowerShell. Skrypty PowerShell są świetne i wiele osób spędza sporo czasu na tym etapie podczas nauki PowerShell. Skrypty pozwalają na utrzymanie rzeczy w miarę prostych i mogą pomóc szybko zautomatyzować zadania. W miarę jak będziesz stawał się coraz lepszy i zaczniesz pisać więcej PowerShell będziesz musiał zwrócić uwagę na tworzenie funkcji PowerShell!
Wideo
Jeśli wolisz format wideo od pisemnej dokumentacji, omawiam ten temat w następującym wideo TechThoughts:
Kiedy powinieneś napisać funkcję PowerShell
Na koniec dnia skrypt PowerShell jest zestawem kodu, który wykonuje zadanie. To właśnie robi również funkcja PowerShell! Więc, dlaczego zdecydowałbyś się napisać funkcję a nie skrypt? Omówimy kilka powodów poniżej. Ogólnie rzecz biorąc, skrypt jest czymś dla Ciebie. Gdy chcesz zacząć dzielić się swoim kodem, lub gdy chcesz, aby Twoi koledzy z zespołu zajęli się nim, będziesz chciał zacząć korzystać z niektórych możliwości, które zapewniają funkcje. Nie ma sztywnej granicy. Dla szybkiego zadania, które zostanie uruchomione jednorazowo na twojej stacji roboczej, skrypt może mieć sens. Jeśli piszesz PowerShell, którego inni mogą używać, lub którego możesz użyć więcej niż raz, funkcja będzie prawdopodobnie lepsza.
- Pojedynczy cel – funkcja jest zazwyczaj używana do wykonywania wąskiego zadania i „robi jedną rzecz, i robi to świetnie”. To sprawia, że funkcje są wysoce wielokrotnego użytku. Jeśli na przykład napiszesz funkcję logowania, możesz następnie użyć tej funkcji logowania PowerShell z innymi funkcjami lub skryptami.
- Pomoc – funkcje obsługują komentarze oparte na pomocy. Dzięki temu użytkownicy mogą robić takie rzeczy jak Get-Help i dowiedzieć się, jak używać funkcji.
- Parametry – wsparcie dla prostych i zaawansowanych deklaracji parametrów i kontroli pozwala funkcji być dynamiczną i przyjmować różne formy danych wejściowych użytkownika.
- Testowalność – funkcje mogą być testowane i wyśmiewane, co znacznie poprawia jakość kodu.
Anatomia funkcji PowerShell
Oto podstawowy układ i kolejność funkcji PowerShell. Poniżej zagłębimy się w każdą z tych sekcji i zbadamy je szczegółowo.
# function help - (optional but strongly encouraged)# function name# CmdletBinding - (optional)# parameters - (optional)# function logic (optional Begin / Process / End)# return - (optional)function Verb-Noun { param ( ) begin { } process { } end { }}
Pomoc funkcji
Gdy umieścisz pomoc na górze swojej funkcji, zostanie ona wyświetlona, gdy Get-Help zostanie uruchomiony przeciwko twojej funkcji. Jest to potężna możliwość, gdy inni badają twój kod. Poświęcenie czasu na stworzenie dobrego synopsis i opisu w połączeniu z solidnymi przykładami pomoże innym zrozumieć do czego służy twoja funkcja i jak jej używać.
Wszystkie pola pomocy są opcjonalne i możesz je dodać lub usunąć według własnego uznania. Zalecam, abyś zawarł co najmniej poniższe pola.
<#.SYNOPSIS Short description.DESCRIPTION Long description.EXAMPLE C:\PS> Example of how to use this cmdlet.EXAMPLE C:\PS> Another example of how to use this cmdlet.PARAMETER InputObject Specifies the object to be processed. You can also pipe the objects to this command..OUTPUTS Output from this cmdlet (if any).NOTES General notes.COMPONENT The component this cmdlet belongs to#>
CmdletBinding
Gdy napiszesz świetną funkcję i nadasz jej nazwę taką jak Get-AllFileInformation, wygląda ona i będzie działać jak cmdlet. Ale jest to ważne rozróżnienie, że funkcja PowerShell nie jest cmdletem. Cmdlet’s są napisane i skompilowane w C#, a funkcja PowerShell jest napisana w PowerShell.
CmdletBinding jest atrybutem funkcji, który umożliwia im działanie bardziej podobne do skompilowanych cmdlet’ów. Dodanie tego atrybutu do funkcji daje jej wiele dodatkowych możliwości takich jak:
- Write-Verbose – pozwala użytkownikom na użycie przełącznika -Verbose aby zobaczyć co robi funkcja w trakcie jej wykonywania.
- ShouldProcess – jeśli funkcja będzie dokonywać zmian w systemie, który jest wysokiego ryzyka, możesz chcieć aby użytkownik potwierdził akcję.
- PositionalBinding – umożliwia uruchomienie funkcji bez konieczności jawnego podawania nazwy każdego parametru. Wartości mogą być wywnioskowane na podstawie kolejności, w jakiej są dostarczane do Twojej funkcji
parametry
param ( $City, $Units = 'USCS', $Language = 'en', $Short)
Parametry służą do zapewnienia użytkownikowi sposobu na dynamiczną interakcję z Twoją funkcją. Możesz przyjmować różne formy danych wejściowych i wykonywać wiele różnych kontroli i walidacji, aby upewnić się, że otrzymujesz właściwy rodzaj informacji.
Możesz pozostać bardzo prosty i zadeklarować tylko nazwy swoich parametrów. Alternatywnie, możesz uzyskać bardzo szczegółowe informacje na temat tego, co jest wymagane dla twoich parametrów:
- Czy parametr jest obowiązkowy
- Pozycja parametru (kolejność)
- Typ parametru (string/int/bool/etc)
- Ustawianie wartości domyślnych
- Weryfikacja wejścia
- Zestawy parametrów
- Wiele więcej
Ten post nie jest w stanie pokryć każdej możliwej konfiguracji parametrów. Nawet po latach pisania PowerShell’a trudno jest mi zapamiętać wszystkie ustawienia parametrów i składnię. Wiedz, że deklaracje parametrów są twoim sposobem na przyjmowanie danych wejściowych do twojej funkcji. Możesz nadać im wiele szczegółów i kontroli, lub po prostu zachować ich prostotę w zależności od potrzeb. Zakładka parametry linki na dole tego postu. Nawet dziś często je odwiedzam!
Begin Process End
Te trzy słowa kluczowe są fazami, które możesz zadeklarować w swojej funkcji.
- Begin zainicjuje niektóre kroki na początku
- Process przetworzy każdy obiekt tak jak go otrzymał
- End może wykonać czyszczenie.
Jest to szczególnie przydatne, jeśli chcesz, aby twoja funkcja wspierała przetwarzanie danych wejściowych z rurociągu.
To może być trudne do uchwycenia w teorii, więc tutaj jest przykład, który demonstruje jego użycie.
function Get-PipelineBeginEnd { param ( $SomeInput ) begin { "Begin: The input is $SomeInput" } process { "The value is: $_" } end { "End: The input is $SomeInput" }}#Get-PipelineBeginEnd1, 2, 3 | Get-PipelineBeginEnd -SomeInput 'Test'
Gdy uruchomisz powyższy kod zauważ, że Begin uruchamia się raz, podobnie jak End. Process jest uruchamiany dla każdego elementu przekazanego do niego, a Process ma dostęp do bieżącego obiektu w potoku.
Logika funkcji
Logika zawarta wewnątrz funkcji PowerShell nie różni się od tej zawartej w skrypcie. Jest to miejsce, w którym napiszesz podstawową logikę, która wykonuje zadanie, do którego dana funkcja jest przeznaczona. Zostało to omówione w odcinkach 1-10 tego kursu. Możesz również zobaczyć pełny przykład na żywo w odcinku Skrypty PowerShell.
Zwracanie funkcji
Nie wszystkie funkcje zwracają coś po uruchomieniu. Jeśli twoja funkcja będzie coś zwracać, możesz opcjonalnie użyć return. Pamiętaj, że gdy użyjesz return, wszystkie dalsze działania w funkcji zostaną zatrzymane, a funkcja zakończy się.
function Get-Total { param ( $Number1, $Number2 ) $total = $Number1 + $Number2 return $total}Get-Total -Number1 2 -Number2 2
W powyższym przykładzie ta prosta funkcja zawiera dwa parametry typu integer. Logika funkcji dodaje te dwie liczby do siebie i zwraca liczbę całkowitą do użytkownika.
Twoja pierwsza funkcja PowerShell
Spójrz na poniższą funkcję PowerShell. Zauważ, że układ funkcji jest zgodny z tym, co opisywaliśmy wcześniej. Zauważ również, że sekcja pomocy dostarcza wielu szczegółów na temat celu i użycia funkcji.
<#.SYNOPSIS Returns your public IP address..DESCRIPTION Queries the ipify Public IP Address API and returns your public IP..EXAMPLE Get-PublicIP Returns the public IP..OUTPUTS System.String.NOTES https://github.com/rdegges/ipify-api#>function Get-PublicIP { $uri = 'https://api.ipify.org' try { $invokeRestMethodSplat = @{ Uri = $uri ErrorAction = 'Stop' } $publicIP = Invoke-RestMethod @invokeRestMethodSplat } catch { Write-Error $_ } return $publicIP}#Get-PublicIP
Jako że logika tej funkcji jest dość prosta, może być kuszące pozostawienie jej jako skryptu. Zauważ jednak, że robi to jedną konkretną rzecz i robi to dobrze. Możesz teraz włączyć tę funkcję do innej zaawansowanej logiki, zamiast odwoływać się do skryptu lub go importować. Inni użytkownicy w twoim środowisku również mogą zacząć korzystać z tej funkcji, gdy się z nią zapoznają.
Zakres funkcji
Jak większość języków, PowerShell ma zasady dotyczące zakresu zmiennych. Kiedy zmienna znajduje się wewnątrz funkcji, nie będziesz już w stanie „zobaczyć” jej wartości. Oto przykład takiego zachowania:
function Get-NumberTimesTwo { param ( $Number ) $total = $Number * 2 return $total}#Get-NumberTimesTwoGet-NumberTimesTwo -Number 2
Funkcja zachowuje się zgodnie z oczekiwaniami i poprawnie mnoży liczbę przez dwa. W swojej konsoli spróbuj jednak zobaczyć, jaka jest wartość $total. Nie będziesz w stanie. Dzieje się tak, ponieważ $total jest przypisane do funkcji, a nie do Twojej aktywnej sesji konsoli.
To może być mylące dla osób nowych w PowerShell i może utrudniać pisanie funkcji. Istnieje kilka strategii radzenia sobie z tym problemem.
Możesz napisać większość swojej logiki w formie skryptu, testując zmienne w trakcie pracy. Kiedy już będziesz pewien, że logika działa zgodnie z założeniami, możesz zawinąć ją w funkcję.
Alternatywnie, możesz użyć Write-Host, Write-Output, lub jeszcze lepiej Write-Debug, aby zobaczyć co się dzieje ze zmiennymi wewnątrz funkcji!
function Get-NumberTimesTwo { param ( $Number ) $total = $Number * 2 Write-Debug $total return $total}#Get-NumberTimesTwoGet-NumberTimesTwo -Number 2 -Debug
Zauważ, że z przełącznikiem debug otrzymujemy dostęp do wartości wewnątrz $total, aby upewnić się, że nasza logika robi to co zamierzamy.
Przykład zamykający
Oto większy przykład zamykający dwie funkcje PowerShella, które umożliwią Ci surfowanie po popularnej stronie reddit przy użyciu PowerShella!
Wejdź na poniższy link GitHub gist, aby uzyskać dostęp do kodu i załadować go do swojej konsoli.
https://gist.github.com/techthoughts2/cd2b720c9b291510cbd643e6ca73e05f
Podczas poznawania tych funkcji postaraj się odpowiedzieć na następujące pytania:
- Z dwóch funkcji, która z nich jest funkcją podstawową?
- Czy są to funkcje standardowe czy zaawansowane?
- Która z funkcji będzie obsługiwała dane wejściowe z potoku?
Additional Reading
- Functions
- Parameters
- Functions Advanced
- Functions Advanced Parameters
- PowerShell Approved Verbs
- CmdletBindingAttribute
Series Navigation << PowerShell ScriptsManage Cloud with PowerShell >>