
Dzisiaj zacznę nietypowo. Spójrz na poniższy fragment kodu i odpowiedź na pytane. Czy to zadziała?
Jeśli od razu pomyślałeś, „nie ma mowy” to problem z przeniesieniem zmiennych lokalnych do poleceń zdalnych nie jest Ci obcy. Jeśli jednak miałeś wątpliwości (spoko, sporo osób je ma) to zapraszam Cię do wpisu, w którym wyjaśniam, dlaczego nie mogło to zadziałać.
Wszystkiemu winny jest…
Zakres sesji
Z zakresem sesji trzeba się zmierzyć, nie tylko używając Invoke-Command
ale również Start-Job
.
Lokalny skrypt jest wykonywany w zakresie innej sesji niż blok skryptu wykonany przez Invoke-Command
lubStart-Job
. Zdefiniowane zmienne $Path
i $Desintation
istnieją tylko w naszej (lokalnej) sesji. Natomiast w zdalnej po prostu ich nie ma, więc mają wartość $null
.
Wykonaj poniższy przykład aby przekonać się, że to napisałem to prawda.
Działa to tak a nie inaczej, ponieważ PowerShell zakłada, że zmienne używane w zdalnych poleceniach zostaną tam zdefiniowane. Czyli PowerShell domyślnie oczekuje czegoś takiego.
Jest to jakieś rozwiązanie, jednak znacznie częściej będziesz chciał przekazać wartości z lokalnego skryptu (sesji) do sesji zdalnej. Co wtedy?
Zobacz 3 podejścia przeniesienia zmiennych lokalnych do poleceń zdalnych.
1. Zmienna automatyczna $args
Wykorzystaj parametr -ArgumentList
polecenia Invoke-Command
lub Start-Job
do przekazania wartości zmiennych. Wartości te trafią (nie zawsze) do automatycznej zmiennej $args
, którą wykorzystasz w bloku skryptu.
Zmienna $args
jest tablicą, dlatego pierwszą wartość znajdziesz w $args[0]
, drugą w $args[1]
i tak dalej.
2. Blok parametrów
Wykorzystaj w bloku skryptu, blok parametrów tak jak w skrypcie lub funkcji. Określ niezbędne parametry, których wartość następnie przekażesz podobnie jak wyżej, poprzez -ArgumentList
.
Jeśli blok skryptu ma zadeklarowane parametry to zmienna automatyczna $args
jest pomijana (stąd te nie zawsze), chyba że argumentów w -ArgumentList
będzie więcej niż parametrów w bloku param()
.
3. Modyfikator zakresu Using:
Począwszy od PowerShell 3.0, sprawa uproszczono maksymalnie. Wystarczy skorzystać z modyfikatora zakresu Using:<nazwa zmiennej>
aby przenieść zmienną lokalną do zdalnego polecenia.
W tym podejściu -ArgumentList
jest kompletnie niepotrzebny. Tylko oznaczamy modyfikatorem w bloku skryptu, które zmienne lokalne zostaną użyte w zdalnej sesji.
Podsumowanie
We wpisie wyjaśniłem, dlaczego występuje problem z przeniesienia zmiennych lokalnych do poleceń zdalnych i jak sobie z nim radzić.
Ostatnia sprawa, jeśli nie musisz zapewniać kompatybilności z PowerShell 2.0 to wykorzystuj w pierwszej kolejności modyfikator sesji Using:
.
Źródła:

Mateusz Nadobnik
Zachwycony językiem skryptowym Windows PowerShell. Swoją wiedzę, doświadczenia i spostrzeżenia opisuję na blogu.
read more