Pagina principala » HOWTO » Cum se utilizează un fișier batch pentru a face scripturile PowerShell mai ușor de rulat

    Cum se utilizează un fișier batch pentru a face scripturile PowerShell mai ușor de rulat

    Din mai multe motive, scripturile PowerShell legate de securitate nu sunt la fel de ușor de portabil și pot fi folosite ca scripturi batch. Cu toate acestea, putem lega un script batch cu scripturile PowerShell pentru a rezolva aceste probleme. Aici, vă vom arăta câteva dintre aceste domenii problematice și cum să construiți un scenariu batch pentru a le înconjura.

    De ce nu pot să-mi copiez fișierul .PS1 pe alt computer și să îl rulez?

    Cu excepția cazului în care sistemul țintă a fost preconfigurat pentru a permite rularea de scripturi arbitrare, cu privilegiile necesare și utilizând setările corecte, este posibil să aveți probleme când încercați să faceți acest lucru.

    1. PowerShell nu este asociat implicit cu extensia .PS1.
      Am adus acest lucru inițial în seria PowerShell Geek School. Windows asociază în mod implicit fișierele .PS1 în Notepad, în loc să le trimită interpretului de comandă PowerShell. Acest lucru este de a preveni executarea accidentală a script-urilor malware prin simpla dublare a acestora. Există modalități prin care puteți schimba acest comportament, dar probabil că nu este ceva pe care doriți să îl faceți pe fiecare computer pe care purtați scripturile în jurul valorii de - mai ales dacă unele dintre aceste computere nu sunt ale dvs..
    2. PowerShell nu permite executarea script-ului extern în mod implicit.
      Setarea ExecutionPolicy din PowerShell previne implicit executarea de script-uri externe în toate versiunile de Windows. În unele versiuni Windows, implicit nu permite executarea script-ului. V-am arătat cum să modificați această setare în Cum să permiteți executarea scripturilor PowerShell pe Windows 7. Totuși, aceasta este și ceva ce nu doriți să faceți pe nici un computer.
    3. Unele scripturi PowerShell nu vor funcționa fără permisiuni de administrator.
      Chiar și cu un cont la nivel de Administrator, tot trebuie să treci prin Controlul Contului de Utilizator (UAC) pentru a efectua anumite acțiuni. Nu vrem să dezactivăm acest lucru, dar este încă plăcut când putem face ceva mai ușor de rezolvat.
    4. Unii utilizatori pot avea personalizate medii PowerShell.
      Probabil că nu veți întâlni acest lucru frecvent, dar când faceți acest lucru, este posibil ca rularea și depanarea scenariilor dvs. să fie puțin frustrante. Din fericire, putem obține acest lucru fără să facem nici o schimbare permanentă.

    Pasul 1: Faceți dublu clic pentru a rula.

    Să începem prin abordarea primei probleme - asociații de dosare .PS1. Nu puteți face dublu clic pentru a rula fișierele .PS1, dar puteți executa un fișier .BAT în acest fel. Deci, vom scrie un fișier batch pentru a apela scriptul PowerShell din linia de comandă pentru noi.

    Deci, nu trebuie să re-scriem fișierul batch pentru fiecare script sau de fiecare dată când mutați un script în jur, va folosi o variabilă de auto-referință pentru a construi calea fișierului pentru scriptul PowerShell. Pentru a face acest lucru, fișierul lot trebuie să fie plasat în același director ca și scriptul dvs. PowerShell și să aibă același nume de fișier. Deci, dacă scriptul dvs. PowerShell este numit "MyScript.ps1", veți dori să denumiți fișierul batch "MyScript.bat" și să vă asigurați că este în același folder. Apoi, puneți aceste linii în scriptul de lot:

    @ECHO OFF PowerShell.exe -Command "&"% ~ dpn0.ps1 "" PAUZĂ

    Dacă nu ar exista alte restricții de securitate în vigoare, ar fi într-adevăr tot ce este necesar pentru a rula un script PowerShell dintr-un fișier batch. De fapt, prima și ultima linie sunt în principal doar o chestiune de preferință - este a doua linie care face într-adevăr munca. Iată defalcarea:

    @CHO OFF dezactivează ecoul de comandă. Acest lucru nu face ca celelalte comenzi să se afișeze pe ecran atunci când rulează fișierul lot. Această linie este ascunsă prin utilizarea simbolului de la (@) din fața acesteia.

    PowerShell.exe -Command "&"% ~ dpn0.ps1 "" de fapt rulează scriptul PowerShell. PowerShell.exe poate fi, desigur, apelat din orice fereastră CMD sau fișier lot pentru a lansa PowerShell la o consolă goală ca de obicei. De asemenea, îl puteți utiliza pentru a rula comenzi direct dintr-un fișier batch, prin includerea parametrului -Command și a argumentelor corespunzătoare. Modul în care este folosit pentru a viza fișierul .PS1 este cu variabila specială% ~ dpn0. Rulați dintr-un fișier batch,% ~ dpn0 evaluează litera de unitate, calea dosarului și numele fișierului (fără extensie) din fișierul batch. Deoarece fișierul batch și scriptul PowerShell vor fi în același director și vor avea același nume,% ~ dpn0.ps1 va traduce în calea fișierului complet al scriptului PowerShell.

    PAUZĂ doar întrerupe execuția lotului și așteaptă introducerea de către utilizator. Acest lucru este în general util pentru a avea la sfârșitul fișierelor lot, astfel încât să aveți șansa de a revizui orice ieșire de comandă înainte ca fereastra să dispară. Pe măsură ce testează fiecare pas, utilitatea acestui lucru va deveni mai evidentă.

    Deci, fișierul de bază de bază este configurat. În scopuri demonstrative, acest fișier este salvat ca "D: \ Script Lab \ MyScript.bat" și există un "MyScript.ps1" în același folder. Să vedem ce se întâmplă atunci când faceți dublu clic pe MyScript.bat.

    Evident, scriptul PowerShell nu a rulat, dar acest lucru este de așteptat - în cele din urmă am abordat doar prima dintre cele patru probleme. Cu toate acestea, există câteva biți importanți demonstrat aici:

    1. Titlul ferestrei arată că scriptul de serie a lansat cu succes PowerShell.
    2. Prima linie de ieșire arată că este folosit un profil PowerShell personalizat. Aceasta este problema potențială nr. 4, menționată mai sus.
    3. Mesajul de eroare demonstrează existența restricțiilor de executare politică. Asta e problema noastră # 2.
    4. Partea subliniată a mesajului de eroare (care se efectuează nativ prin ieșirea de eroare a PowerShell) arată că script-ul batch a vizat corect scriptul PowerShell intenționat (D: \ Script Lab \ MyScript.ps1). Deci, cel puțin știm că multe lucruri funcționează corect.

    Profilul, în acest caz, este un script simplu dintr-o singură linie utilizat pentru această demonstrație pentru a genera ieșire ori de câte ori profilul este activ. Puteți personaliza propriul profil PowerShell și pentru a face acest lucru, dacă doriți să testați aceste scripturi. Pur și simplu adăugați următoarea linie în scriptul de profil:

    Scriere-ieșire 'Profil personalizat PowerShell în vigoare!'

    Execuția politică din sistemul de testare este setată la RemoteSigned. Acest lucru permite executarea de script-uri create local (cum ar fi scriptul de profil), în timp ce blocarea scripturilor din surse externe, cu excepția cazului în care sunt semnate de o autoritate de încredere. În scopuri demonstrative, următoarea comandă a fost utilizată pentru a semnala MyScript.ps1 ca fiind dintr-o sursă externă:

    Add-Content -Path "D: \ Script Lab \ MyScript.ps1" -Value "[ZoneTransfer] 'nZoneId = 3" -Stream' Zone.Identifier '

    Aceasta stabilește fluxul de date alternativ pentru Zone.Identifier pe MyScript.ps1, astfel încât Windows să creadă că fișierul a venit de pe Internet. Se poate inversa ușor cu următoarea comandă:

    Clear-Content -Path "D: \ Script Lab \ MyScript.ps1 '-Stream' Zone.Identifier '

    Pasul 2: Învățați politica de execuție.

    Noțiuni de bază despre setarea ExecutionPolicy, de la CMD sau un script batch, este de fapt destul de ușor. Modificăm doar linia a doua a scriptului pentru a adăuga un alt parametru comenzii PowerShell.exe.

    PowerShell.exe -ExecuțiePoliția Bypass -Command "&"% ~ dpn0.ps1 ""

    Parametrul -ExecutionPolicy poate fi utilizat pentru a modifica ExecutionPolicy care se utilizează atunci când faceți o nouă sesiune PowerShell. Acest lucru nu va persista dincolo de acea sesiune, astfel încât să putem rula PowerShell astfel de ori de câte ori avem nevoie fără a slăbi postura generală de securitate a sistemului. Acum că am rezolvat asta, să mai mergem la el:

    Acum că scriptul a executat corect, putem vedea ce face de fapt. Ne anunță că executăm scriptul ca utilizator limitat. Scriptul este, de fapt, gestionat de un cont cu permisiuni de administrator, dar controlul contului de utilizator devine în cale. Deși detaliile privind modul în care scriptul verifică accesul administratorului depășesc domeniul de aplicare al acestui articol, iată codul folosit pentru demonstrație:

    dacă [([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()) IsInRole ([Security.Principal.WindowsBuiltInRole] "Administrator")) Write-Output 'Running as Administrator! Write-Output 'Running Limited!' Pauză

    De asemenea, veți observa că există două operațiuni "Pause" în ieșirea scriptului - una din scriptul PowerShell și una din fișierul batch. Motivul pentru aceasta va fi mai evident în următorul pas.

    Pasul 3: Obținerea accesului la administratori.

    Dacă scriptul dvs. nu rulează comenzi care necesită elevație și sunteți destul de sigur că nu va trebui să vă faceți griji cu privire la faptul că profilurile personalizate ale cuiva se blochează, puteți trece peste restul acestora. Dacă rulați unele cmdlet-uri la nivel de administrator, veți avea nevoie de această piesă.

    Din păcate, nu există nicio modalitate de a declanșa UAC pentru elevație din cadrul unui fișier batch sau al unei sesiuni CMD. Cu toate acestea, PowerShell ne permite să facem acest lucru cu Start-Process. Când se utilizează cu "-Verb RunAs" în argumentele sale, Start-Process va încerca să lanseze o aplicație cu permisiuni Administrator. Dacă sesiunea PowerShell nu este deja ridicată, aceasta va declanșa o solicitare UAC. Pentru a folosi acest lucru din fișierul batch pentru lansarea scriptului nostru, vom termina două procese PowerShell - unul pentru a declanșa Start-Process și altul lansat de Start-Process pentru a rula scriptul. A doua linie a fișierului batch trebuie modificată la următoarea:

    PowerShell.exe -Command "& Start-Process PowerShell.exe -ArgumentList '-ExecuțiePolicel Bypass -File" "% ~ dpn0.ps1" "-Verb RunAs"

    Când se execută fișierul lot, prima linie de ieșire pe care o vom vedea este din scriptul profilului PowerShell. Apoi, va exista un prompt UAC când Start-Process încearcă să lanseze MyScript.ps1.

    După ce faceți clic pe promptul UAC, va apărea o nouă instanță PowerShell. Deoarece aceasta este o instanță nouă, bineînțeles, vom vedea din nou anunțul de script de profil. Apoi, MyScript.ps1 rulează și vedem că suntem cu adevărat într-o sesiune ridicată.

    Și există motivul pentru care avem și două pauze aici. Dacă nu pentru cea din scriptul PowerShell, nu vom vedea niciodată ieșirea scriptului - fereastra PowerShell va apărea și va dispărea imediat ce scriptul este terminat. Și fără pauză în fișierul lot, nu am fi putut să vedem dacă au apărut erori în primul rând în PowerShell.

    Pasul 4: Obținerea profilelor personalizate PowerShell.

    Hai să scăpăm de anunțul ăsta de profil personalizat acum, nu? În acest caz, este greu de comportat, dar dacă profilul PowerShell al unui utilizator modifică setările implicite, variabilele sau funcțiile în moduri pe care nu le-ați anticipat cu scenariul dvs., acestea pot fi cu adevărat deranjante. Este mult mai simplu să rulați scenariul fără profilul complet, astfel încât să nu vă faceți griji în legătură cu acest lucru. Pentru a face acest lucru, trebuie doar să schimbăm a doua linie a fișierului lot încă o dată:

    PowerShell.exe -NoProfile -Command "și Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecuțiePolitică Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"

    Adăugarea parametrului -NoProfile la ambele instanțe ale PowerShell lansate de script înseamnă că scriptul de profil al utilizatorului va fi complet ocolit în ambele etape, iar scriptul PowerShell va rula într-un mediu destul de previzibil, implicit. Aici, puteți vedea că nu există nicio notificare de profil personalizată în niciuna din cochilii care au dat naștere.

    Dacă nu aveți nevoie de drepturi de administrator în scriptul dvs. PowerShell și ați sărit peste pasul 3, puteți să faceți acest lucru fără a doua instanță PowerShell și a doua linie a fișierului dvs. batch ar trebui să arate astfel:

    PowerShell.exe -NoProfile -ExecuțiePolitica Bypass -Command "&"% ~ dpn0.ps1 ""

    Ieșirea va arăta astfel:

    (Desigur, pentru scripturile non-Administrator, puteți face și fără o pauză de sfârșit de script în scriptul PowerShell în acest moment, deoarece totul este capturat în aceeași fereastră a consolei și va fi ținut acolo de pauza de la sfârșitul fișierul batch oricum.)

    Fișiere batch completate.

    În funcție de faptul dacă aveți sau nu nevoie de permisiuni de administrator pentru scriptul dvs. PowerShell (și nu ar trebui să le cereți dacă nu faceți acest lucru), fișierul final de lot ar trebui să arate ca unul dintre cele două de mai jos.

    Fără acces Admin:

    @CHO OFF PowerShell.exe -NoProfile -ExecuțiePolitica Bypass -Command "&"% ~ dpn0.ps1 "" PAUZĂ

    Cu acces Admin:

    @CHO OFF PowerShell.exe -NoProfile -Command "& Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecuțiePolice Bypass -File" "% ~ dpn0.ps1" "-Verb RunAs" PAUZĂ

    Nu uitați să puneți fișierul batch în același director ca și scriptul PowerShell pe care doriți să-l utilizați și să-i dați același nume. Apoi, indiferent de sistemul în care faceți aceste fișiere, veți putea să rulați scriptul dvs. PowerShell fără a fi nevoit să vă răsturnați cu oricare dintre setările de securitate ale sistemului. Cu siguranță puteți face aceste modificări manual de fiecare dată, dar acest lucru vă salvează acea problemă și nu va trebui să vă faceți griji cu privire la revenirea modificărilor ulterior.


    Referințe:

    • Rularea scripturilor PowerShell dintr-un fișier batch - Blogul de programare al lui Daniel Schroeder
    • Verificarea permisiunilor de administrator în PowerShell - Hei, Scripting Guy! Blog