W skryptach wsadowych zmiany zmiennych środowiskowych mają globalny wpływ na bieżącą sesję domyślnie. W przypadku programu PowerShell dokładne przeciwieństwo jest prawdziwe, ponieważ zakresy służą do izolowania modyfikacji skryptu. W tym artykule omawiamy, w jaki sposób zakresy wpływają na skrypty PowerShell i jak pracować w nich i wokół nich.
W PowerShell "zakres" odnosi się do bieżącego środowiska, w którym działa skrypt lub warstwa poleceń. Zakresy służą do ochrony pewnych obiektów w środowisku przed niechcący zmodyfikowanym przez skrypty lub funkcje. W szczególności następujące rzeczy są chronione przed modyfikacją przez polecenia uruchamiane z innego zakresu, chyba że parametry w tych komendach określają inaczej:
Nowe zakresy są tworzone za każdym razem, gdy uruchamiasz skrypt lub funkcję, lub gdy tworzysz nową sesję lub wystąpienie PowerShell. Zakresy tworzone przez uruchamianie skryptów i funkcji mają relację "nadrzędny / podrzędny" z zakresem, w którym zostały utworzone. Istnieje kilka zakresów, które mają szczególne znaczenie i można je uzyskać po nazwie:
Zakresy mogą być również określane numerami w niektórych poleceniach, gdzie bieżący zakres jest określany jako zero, a do jego przodków odwołują się rosnące liczby całkowite. Na przykład w skrypcie uruchamianym z zasięgu globalnego zasięg skryptu będzie wynosił 0, a zasięg globalny będzie wynosił 1. Zakres, który był dalej zagnieżdżony w zasięgu Skryptu, taki jak funkcja, odnosiłby się do zakresu globalnego jako 2. Liczby ujemne nie będą jednak działały w odniesieniu do zakresów potomnych - przyczyna tego będzie widoczna wkrótce.
Jak wspomniano wcześniej, polecenia wykonywane w ramach jednego zakresu nie będą miały wpływu na rzeczy w innym zakresie, chyba że zostanie im to wyraźnie powiedziane. Na przykład, jeśli $ MyVar istnieje w zasięgu globalnym, a skrypt uruchamia polecenie ustawienia zmiennej $ MyVar na inną wartość, wersja globalna zmiennej $ MyVar pozostanie niezmieniona, podczas gdy kopia zmiennej $ MyVar zostanie umieszczona w zakresie Skrypt z nowym wartość. Jeśli plik $ MyVar nie istnieje, skrypt utworzy go domyślnie w zakresie Skrypt - nie w zasięgu globalnym. Jest to ważne, aby pamiętać, kiedy dowiesz się o rzeczywistej relacji rodzic / dziecko między zakresami.
Relacja rodzic / dziecko zakresów w PowerShell jest jednokierunkowa. Polecenia mogą przeglądać i opcjonalnie modyfikować bieżący zakres, jego element nadrzędny i wszelkie zakresy powyżej. Jednak nie mogą widzieć ani modyfikować rzeczy w żadnych dzieciach z bieżącego zakresu. Dzieje się tak głównie dlatego, że po przejściu do zakresu nadrzędnego zakres podrzędny został już zniszczony, ponieważ spełnił swój cel. Na przykład, dlaczego musiałbyś widzieć lub modyfikować zmienną w zakresie Skrypt, z zakresu globalnego po zakończeniu działania skryptu? Istnieje wiele przypadków, w których potrzebne są zmiany skryptu lub funkcji, które utrzymają się po zakończeniu, ale nie tak wiele, gdy trzeba wprowadzić zmiany do obiektów w zakresie skryptu lub funkcji przed lub po uruchomieniu. (Zwykle takie rzeczy będą mimo wszystko obsługiwane jako część skryptu lub funkcji).
Oczywiście, czym są reguły bez wyjątków? Jeden wyjątek od powyższego to Prywatne zakresy. Obiekty w zakresach prywatnych są dostępne tylko dla poleceń uruchamianych w zakresie, w którym zostały utworzone. Innym ważnym wyjątkiem są elementy, które mają właściwość AllScope. Są to specjalne zmienne i aliasy, dla których zmiana dowolnego zakresu będzie dotyczyć wszystkich zakresów. Poniższe polecenia pokazują, które zmienne i aliasy mają właściwość AllScope:
Pobierz zmienną | Where-Object $ _. Opcje -match 'AllScope' Get-Alias | Gdzie-obiekt $ _. Opcje-zestaw "AllScope")
Nasze pierwsze spojrzenie na zakresy w akcji rozpoczniemy w sesji PowerShell, w której zmienna $ MyVar została ustawiona na ciąg znaków "Jestem zmienną globalną!" Z wiersza poleceń. Następnie z pliku o nazwie Scope-Demo.ps1 zostanie uruchomiony następujący skrypt:
Funkcja FunctionScope 'Zmiana $ MyVar za pomocą funkcji.' $ MyVar = 'Ustawiłem przez funkcję!' "MyVar mówi $ MyVar" "Sprawdzanie bieżącej wartości MyVar." "MyVar mówi MyVar" "Zmienia $ MyVar według skryptu." $ MyVar = 'Ustawiłem przez skrypt! " "MyVar mówi" MyVar "" "FunctionScope" Sprawdzanie końcowej wartości MyVar przed wyjściem skryptu. " "MyVar mówi $ MyVar" "
Gdyby skrypty PowerShell działały tak samo jak skrypty wsadowe, spodziewalibyśmy się, że zmienna $ MyVar (lub% MyVar% w składni wsadowej) zmieni się z "Jestem zmienną globalną!", Na "Ustawiłem przez skrypt!" , a na końcu do "Ustawiłem przez funkcję!" gdzie pozostanie, dopóki nie zostanie wyraźnie zmieniony ponownie lub sesja zostanie zakończona.Zobacz jednak, co faktycznie się dzieje tutaj, gdy przechodzimy przez każdy z zakresów - w szczególności po zakończeniu funkcji FunctionScope i ponownie sprawdzamy zmienną ze Skryptu, a następnie Globalnego zakresu.
Jak widać, zmienna zmieniła się, gdy przechodziliśmy przez skrypt, ponieważ aż do zakończenia funkcji FunctionScope sprawdzaliśmy zmienną z tego samego zakresu, w którym została ona ostatnio zmieniona. Po zakończeniu działania funkcji FunctionScope wróciliśmy do zakresu Skrypt, w którym funkcja $ MyVar została nietknięta przez funkcję. Następnie, gdy skrypt się zakończył, wróciliśmy do zasięgu globalnego, w którym nie zostało ono w ogóle zmodyfikowane.
Jest więc dobrze i dobrze, aby zapobiec przypadkowemu wprowadzeniu zmian w środowisku poza skrypty i funkcje, ale co, jeśli rzeczywiście chcesz wprowadzić takie modyfikacje? Istnieje specjalna i dość prosta składnia do tworzenia i modyfikowania obiektów poza zasięgiem lokalnym. Po prostu wstawiono nazwę zakresu na początku nazwy zmiennej i wstawiono dwukropek między nazwą zakresu i zmienną. Lubię to:
$ global: Skrypt MyVar $: MyVar $ local: MyVar
Możesz użyć tych modyfikatorów zarówno podczas przeglądania i ustawiania zmiennych. Zobaczmy, co stanie się z tym skryptem demonstracyjnym:
Funkcja FunctionScope "Zmiana $ MyVar w lokalnym zakresie funkcji ... '$ local: MyVar =" To jest MyVar w zasięgu lokalnym funkcji. "" Zmiana $ MyVar w zakresie skryptu ... "$ script: MyVar =' MyVar był kiedyś ustawione przez skrypt, teraz ustawione przez funkcję. "Zmiana $ MyVar w zasięgu globalnym ..." $ global: MyVar = 'MyVar został ustawiony w zasięgu globalnym. Teraz ustawione przez funkcję. "Sprawdzanie $ MyVar w każdym zasięgu ..." "Lokalne: $ local: MyVar" "Script: $ script: MyVar" "Global: $ global: MyVar" "" Otrzymywanie aktualnej wartości $ MyVar. " "MyVar mówi MyVar" "Zmienia $ MyVar według skryptu." $ MyVar = 'Ustawiłem przez skrypt! " "MyVar mówi MyVar" FunctionScope "Sprawdzanie $ MyVar z zakresu skryptu przed zakończeniem." "MyVar mówi $ MyVar" "
Tak jak poprzednio, zaczniemy od ustawienia zmiennej w zasięgu globalnym i zakończymy sprawdzaniem końcowego wyniku globalnego zasięgu.
Tutaj widać, że FunctionScope był w stanie zmienić zmienną w zakresie Skrypt, a zmiany pozostały po jej zakończeniu. Również zmiana zmiennej w zasięgu globalnym trwała nawet po wyjściu skryptu. Może to być szczególnie przydatne, jeśli musisz wielokrotnie zmieniać zmienne w skrypcie lub w zasięgu globalnym, używając tego samego kodu - po prostu definiujesz funkcję lub skrypt, który został napisany w celu zmodyfikowania zmiennej gdzie i jak tego potrzebujesz, oraz wzywaj tego, kiedy tylko konieczne są te zmiany.
Jak wspomniano wcześniej, numery zakresów mogą być również używane w niektórych poleceniach do modyfikowania zmiennej na różnych poziomach w odniesieniu do zasięgu lokalnego. Oto ten sam skrypt, który został użyty w drugim przykładzie powyżej, ale z funkcją zmodyfikowaną tak, aby używać poleceń Get-Variable i Set-Variable z numerami zakresu zamiast bezpośrednio odwoływać się do zmiennej o nazwanych zakresach:
Funkcja FunctionScope "Zmiana $ MyVar w zakresie 0, w stosunku do FunctionScope ..." Set-Variable MyVar "To jest MyVar w zakresie funkcji 0." -Scope 0 "Zmiana $ MyVar w zakresie 1, w stosunku do FunctionScope ... 'Set-Variable MyVar "MyVar został zmieniony w zakresie 1, z funkcji." -Scope 1 'Zmienianie $ MyVar w zakresie 2, względem Functionscope ...' Set-Variable MyVar 'MyVar został zmieniony w zakresie 2, z funkcji.' -Scope 2 "Sprawdzanie $ MyVar w każdym z zakresów ..." Zakres 0: "Zmienna Get MyVar -Scope 0 -ValueOnly" Zakres 1: "Zmienna" Get MyVar -Scope 1 -ValueOnly "Zakres 2:" Get-Variable MyVar -Scope 2 -ValueOnly "" Pobranie aktualnej wartości MyVar $. " "MyVar mówi MyVar" "Zmienia $ MyVar według skryptu." $ MyVar = 'Ustawiłem przez skrypt! " "MyVar mówi MyVar" FunctionScope "Sprawdzanie $ MyVar z zakresu skryptu przed zakończeniem." "MyVar mówi $ MyVar" "
Podobnie jak wcześniej, możemy zobaczyć, jak polecenia z jednego zakresu mogą modyfikować obiekty w zakresie nadrzędnym.
Nadal można zrobić o wiele więcej, niż można to zrobić w tym artykule. Zakresy dotyczą więcej niż tylko zmiennych, a jeszcze więcej można się dowiedzieć o zakresach prywatnych i zmiennych AllScope. Aby uzyskać więcej przydatnych informacji, możesz uruchomić następujące polecenie z poziomu PowerShell:
Uzyskaj pomoc about_scopes
Ten sam plik pomocy jest również dostępny w witrynie TechNet.
Zakres obrazu kredyt: spadassin na openclipart