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:

22 Najważniejsze Wskazówki Pisania Skryptów PowerShell

Mateusz Nadobnik

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

read more