9Sep

Jak korzystać z pliku wsadowego, aby skrypty PowerShell łatwiej działały

Z kilku powodów, głównie związane z bezpieczeństwem, skrypty PowerShell nie są tak łatwo przenośne i użyteczne, jak mogą być skrypty wsadowe. Możemy jednak łączyć skrypt wsadowy ze skryptami PowerShell, aby obejść te problemy. Tutaj pokażemy kilka z tych problematycznych obszarów i jak zbudować skrypt wsadowy, aby je ominąć.

Dlaczego nie mogę skopiować pliku. PS1 na inny komputer i uruchomić go?

Jeśli system docelowy nie został wstępnie skonfigurowany w celu umożliwienia uruchamiania dowolnych skryptów, wymaganych uprawnień i użycia odpowiednich ustawień, istnieje duże prawdopodobieństwo, że napotkasz problemy podczas próby wykonania tego.

  1. PowerShell nie jest domyślnie skojarzony z rozszerzeniem. PS1.
    Początkowo wprowadziliśmy to w naszej serii PowerShell Geek School. Windows domyślnie kojarzy pliki. PS1 z Notatnikiem, zamiast wysyłać je do interpretera poleceń PowerShell. Ma to na celu zapobieganie przypadkowemu uruchamianiu złośliwych skryptów poprzez dwukrotne kliknięcie ich. Są sposoby na zmianę tego zachowania, ale prawdopodobnie nie jest to coś, co chcesz zrobić na każdym komputerze, na którym masz swoje skrypty - zwłaszcza jeśli niektóre z tych komputerów nie są twoje.
  2. PowerShell domyślnie nie pozwala na zewnętrzne wykonywanie skryptów.
    Ustawienie ExecutionPolicy w programie PowerShell uniemożliwia domyślne wykonywanie skryptów zewnętrznych we wszystkich wersjach systemu Windows. W niektórych wersjach systemu Windows ustawienie domyślne nie pozwala na wykonanie skryptu. Pokazaliśmy, jak zmienić to ustawienie w Jak umożliwić wykonywanie skryptów PowerShell w systemie Windows 7. Jest to jednak także coś, czego nie chcesz robić na żadnym komputerze.
  3. Niektóre skrypty PowerShell nie będą działały bez uprawnień administratora.
    Nawet działając z kontem na poziomie administratora, nadal musisz przejść przez kontrolę konta użytkownika( UAC), aby wykonać określone czynności. Nie chcemy tego wyłączać, ale nadal jest przyjemnie, kiedy możemy sobie z tym poradzić.
  4. Niektórzy użytkownicy mogą mieć dostosowane środowiska PowerShell.
    Prawdopodobnie nie natkniesz się na to często, ale kiedy to zrobisz, możesz sprawić, że uruchamianie i rozwiązywanie problemów z twoimi skryptami będzie trochę frustrujące. Na szczęście możemy obejść to bez wprowadzania stałych zmian.

Krok 1: Kliknij dwukrotnie, aby uruchomić.

Zacznijmy od zaadresowania pierwszego problemu - powiązań plików. PS1.Nie można dwukrotnie kliknąć, aby uruchomić pliki. PS1, ale można w ten sposób wykonać plik. BAT.Tak więc, napiszemy plik wsadowy, aby wywołać skrypt PowerShell z linii poleceń dla nas.

Nie musimy więc ponownie pisać pliku wsadowego dla każdego skryptu, lub za każdym razem, gdy przenosimy skrypt, użyjemy zmiennej samoodnośnej do zbudowania ścieżki pliku dla skryptu PowerShell. Aby to działało, plik wsadowy musi być umieszczony w tym samym folderze, co skrypt PowerShell i mieć tę samą nazwę pliku. Jeśli więc twój skrypt PowerShell nazywa się "MyScript.ps1", będziesz chciał nazwać swój plik wsadowy "MyScript.bat" i upewnić się, że znajduje się w tym samym folderze. Następnie umieść te wiersze w skrypcie wsadowym:

@ECHO OFF PowerShell.exe - Polecenie "&%% dpn0.ps1" "PAUSE

Gdyby nie inne ograniczenia bezpieczeństwa w miejscu, to naprawdę byłoby wszystkoto wymaga uruchomienia skryptu PowerShell z pliku wsadowego. W rzeczywistości pierwsza i ostatnia linia to głównie kwestia preferencji - to druga linia naprawdę wykonuje pracę.Oto podział:

@ECHO OFF wyłącza echo poleceń.Dzięki temu pozostałe polecenia nie będą wyświetlane na ekranie podczas działania pliku wsadowego. Linia ta jest sama ukryta za pomocą symbolu at( @) przed nią.

PowerShell.exe -Command "&"% ~ Dpn0.ps1" " faktycznie uruchamia skrypt PowerShell. PowerShell.exe można oczywiście wywołać z dowolnego okna CMD lub pliku wsadowego, aby uruchomić PowerShell na zwykłej konsoli. Można go również użyć do uruchamiania poleceń bezpośrednio z pliku wsadowego, włączając parametr -Command i odpowiednie argumenty. Sposób w jaki cel ten jest kierowany na nasz plik. PS1 jest ze specjalną zmienną% ~ dpn0.Uruchom z pliku wsadowego,% ~ dpn0 ocenia literę dysku, ścieżkę folderu i nazwę pliku( bez rozszerzenia) pliku wsadowego. Ponieważ plik wsadowy i skrypt PowerShell znajdują się w tym samym folderze i mają tę samą nazwę, plik% ~ dpn0.ps1 zostanie przetłumaczony na pełną ścieżkę do pliku skryptu PowerShell.

PAUSE po prostu zatrzymuje wykonanie wsadowe i czeka na wejście użytkownika. Na ogół jest to przydatne na końcu plików wsadowych, dzięki czemu masz szansę przejrzenia dowolnego polecenia, zanim zniknie okno. Kiedy będziemy testować każdy krok, użyteczność tego stanie się bardziej oczywista.

W ten sposób konfigurowany jest podstawowy plik wsadowy. W celach demonstracyjnych plik ten jest zapisywany jako "D: \ Script Lab \ MyScript.bat", aw tym samym folderze znajduje się plik "MyScript.ps1".Zobaczmy, co się stanie, gdy dwukrotnie klikniemy MyScript.bat.

Oczywiście skrypt PowerShell nie działał, ale można się tego spodziewać - w końcu rozwiązaliśmy tylko pierwszy z naszych czterech problemów. Pokazano tu jednak kilka ważnych bitów:

  1. Tytuł okna pokazuje, że skrypt wsadowy pomyślnie uruchomił PowerShell.
  2. Pierwszy wiersz danych wyjściowych pokazuje, że niestandardowy profil PowerShell jest w użyciu. Jest to potencjalny problem nr 4, wymieniony powyżej.
  3. Komunikat o błędzie pokazuje obowiązujące ograniczenia ExecutionPolicy. To nasz problem # 2.
  4. Podkreślona część komunikatu o błędzie( wykonywana natywnie przez wyjście błędów programu PowerShell) pokazuje, że skrypt wsadowy poprawnie atakował zamierzony skrypt PowerShell( D: \ Script Lab \ MyScript.ps1).Więc przynajmniej wiemy, że wiele działa poprawnie.

W tym przypadku profil jest prostym, jednokreskowym skryptem używanym do tej demonstracji do generowania danych wyjściowych za każdym razem, gdy profil jest aktywny. Możesz również dostosować swój profil PowerShell, aby to zrobić, jeśli chcesz przetestować te skrypty samemu. Wystarczy dodać następujący wiersz do swojego skryptu profilu:

"Niestandardowy profil PowerShell Write-Output"!

Opcja ExecutionPolicy w systemie testowym jest ustawiona na RemoteSigned. Pozwala to na wykonywanie skryptów tworzonych lokalnie( jak skrypt profilu), blokując skrypty ze źródeł zewnętrznych, chyba że są podpisane przez zaufane instytucje. W celu demonstracji użyto następującej komendy do oznaczenia pliku MyScript.ps1 jako pochodzącego ze źródła zewnętrznego:

Add-Content-Path 'D: \ Script Lab \ MyScript.ps1' -Vue "[ZoneTransfer]` nZoneId = 3 "-Strumień "Zone. Identifier"

Ustawia alternatywny strumień danych Zone. Identifier w MyScript.ps1, aby system Windows mógł myśleć, że plik pochodzi z Internetu. Można go łatwo odwrócić za pomocą następującej komendy:

Wyczyść-treść -Path 'D: \ Skrypt Lab \ MyScript.ps1' -Stream 'Zone. Identifier'

Krok 2: Poruszanie się w ExecutionPolicy.

Poruszanie się po ustawieniu ExecutionPolicy z CMD lub skryptu wsadowego jest w rzeczywistości dość łatwe. Po prostu modyfikujemy drugą linię skryptu, aby dodać jeszcze jeden parametr do polecenia PowerShell.exe.

PowerShell.exe -ExecutionPolicy Bypass -Command "&%% dpn0.ps1" "

Parametr -ExecutionPolicy może być używany do modyfikowania ExecutionPolicy używanej podczas tworzenia nowej sesji PowerShell. Nie będzie to trwało dłużej niż ta sesja, więc możemy uruchamiać program PowerShell w taki sposób, ilekroć zajdzie taka potrzeba, bez osłabiania ogólnej pozycji bezpieczeństwa systemu. Teraz, gdy już to naprawiliśmy, spójrzmy jeszcze raz:

Teraz, gdy skrypt został poprawnie wykonany, możemy zobaczyć, co on właściwie robi. Informuje nas, że uruchamiamy skrypt jako użytkownik z ograniczonym dostępem. Skrypt jest uruchamiany przez konto z uprawnieniami administratora, ale kontrola konta użytkownika staje na przeszkodzie. Chociaż szczegóły tego, jak skrypt sprawdza dostęp administratora, są poza zakresem tego artykułu, oto kod, który jest używany do demonstracji:

if( ([Security. Principal. WindowsPrincipal] [Security. Principal. WindowsIdentity]: : GetCurrent( IsInRole( [Security. Principal. WindowsBuiltInRole] "Administrator")){ Write-Output "Działa jako Administrator!"} Else{ Write-Output 'Running Limited!'} Wstrzymaj

Zauważysz także, że są teraz dwaOperacje "Wstrzymaj" w wyjściu skryptu - jeden ze skryptu PowerShell, a drugi z pliku wsadowego. Powód tego będzie bardziej widoczny w następnym kroku.

Krok 3: Uzyskiwanie dostępu administratora.

Jeśli twój skrypt nie uruchamia żadnych poleceń, które wymagają podniesienia, i jesteś pewien, że nie będziesz musiał się martwić, że jakiekolwiek niestandardowe profile przeszkadzają, możesz pominąć resztę.Jeśli jednak używasz niektórych cmdletów na poziomie administratora, potrzebujesz tego elementu.

Niestety, nie ma sposobu na wyzwolenie UAC do podniesienia z pliku wsadowego lub sesji CMD.Jednak PowerShell pozwala nam to zrobić w Start-Process. W przypadku użycia z "-Verb RunAs" w swoich argumentach, Start-Process spróbuje uruchomić aplikację z uprawnieniami administratora. Jeśli sesja PowerShell nie została jeszcze podniesiona, spowoduje to wyświetlenie monitu UAC.Aby użyć tego z pliku wsadowego do uruchomienia naszego skryptu, skończymy z utworzeniem dwóch procesów PowerShell - jeden do uruchomienia procesu Start i innego, uruchamianego przez Start-Process, w celu uruchomienia skryptu. Druga linia pliku wsadowego musi zostać zmieniona na:

PowerShell.exe - Polecenie "&{ Rozpocznij przetwarzanie PowerShell.exe -ArgumentList" -OdkrywaniePolicy Obejście -Plik ""% ~ dpn0.ps1 "" -VerbRunAs} "

Po uruchomieniu pliku wsadowego pierwszy wiersz danych wyjściowych, który zobaczymy, pochodzi ze skryptu profilu PowerShell. Następnie pojawi się monit UAC, gdy Start-Process spróbuje uruchomić MyScript.ps1.

Po kliknięciu w monit UAC pojawi się nowa instancja PowerShell. Ponieważ jest to nowa instancja, oczywiście, zobaczymy ponownie powiadomienie dotyczące profilu. Następnie działa MyScript.ps1 i widzimy, że rzeczywiście jesteśmy w podwyższonej sesji.

I jest powód, dla którego mamy tu dwie przerwy. Gdyby nie ten, który znajduje się w skrypcie PowerShell, nigdy nie zobaczylibyśmy wyjścia skryptu - okno PowerShell po prostu wyskakuje i znika, gdy tylko skrypt zostanie uruchomiony. Bez zatrzymania się w pliku wsadowym nie bylibyśmy w stanie stwierdzić, czy były jakieś błędy uruchamiające PowerShell.

Krok 4: Poruszanie się po niestandardowych profilach PowerShell.

Pozbądźmy się teraz tego paskudnego powiadomienia o profilu niestandardowym, dobrze? W tym przypadku nie jest to uciążliwe, ale jeśli profil PowerShell użytkownika zmienia ustawienia domyślne, zmienne lub funkcje w sposób, jakiego mógłbyś nie przewidzieć przy swoim skrypcie, mogą one być naprawdę kłopotliwe. O wiele łatwiej jest uruchomić swój skrypt bez profilu, więc nie musisz się o to martwić.Aby to zrobić, wystarczy jeszcze raz zmienić drugi wiersz pliku wsadowego:

PowerShell.exe -NoProfile -Command "&{ Start-Process PowerShell.exe -ArgumentList" -NoProfile -ExecutionPolicy Bypass -File ""% ~ dpn0.ps1 "" "-Verb RunAs}"

Dodanie parametru -NoProfile do obu wystąpień programu PowerShell uruchamianych przez skrypt oznacza, że ​​skrypt profilu użytkownika zostanie całkowicie pominięty w obu krokach, a nasz skrypt PowerShell będzie działał wdość przewidywalne, domyślne środowisko. Tutaj możesz zauważyć, że w żadnej z zarodkowanych powłok nie ma niestandardowego powiadomienia o profilu.

Jeśli nie potrzebujesz uprawnień administratora w skrypcie PowerShell, a pominiesz krok 3, możesz obejść się bez drugiej instancji PowerShell, a druga linia pliku wsadowego powinna wyglądać następująco:

PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1" "

Dane wyjściowe będą wyglądały następująco:

( Oczywiście, w przypadku skryptów innych niż Administrator, można wykonać bez pauzy końca skryptu w skrypcie PowerShelltakże w tym momencie, ponieważ wszystko jest przechwytywane w tym samym oknie konsoli i będzie tam trzymane przez przerwę na końcu pliku wsadowego.)

Ukończone pliki wsadowe.

W zależności od tego, czy potrzebujesz uprawnień administratora do skryptu PowerShell( i naprawdę nie powinieneś żądać ich, jeśli tego nie robisz), ostateczny plik wsadowy powinien wyglądać jak jeden z dwóch poniższych.

Bez uprawnień administratora:

@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass - Polecenie "&%% dpn0.ps1" "PAUSE

Z dostępem administratora:

@ECHO OFF PowerShell.exe -NoProfile -Command" &{Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File ""% ~ dpn0.ps1 "" -Verb RunAs} "PAUSE

Pamiętaj, aby umieścić plik wsadowy w tym samym folderze, co skrypt PowerShell, który chceszużywać go i nadawać mu tę samą nazwę.Wtedy, bez względu na to, do jakiego systemu przeniesiesz te pliki, będziesz mógł uruchomić swój skrypt PowerShell, bez konieczności obrzucania go jakimikolwiek ustawieniami bezpieczeństwa w systemie. Z pewnością możesz ręcznie wprowadzić te zmiany za każdym razem, ale to oszczędza ci kłopotów i nie będziesz musiał się martwić, że później powrócisz.

Referencje:

  • Uruchamianie skryptów PowerShell z pliku wsadowego - Blog programisty Daniela Schroedera
  • Sprawdzanie uprawnień administratora w PowerShell - Hej, skrypciarze! Blog