If-Koubou

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 (Cum să)

Din mai multe motive, scripturile PowerShell, în mare parte 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 zone problematice și cum să construiți un scenariu batch pentru a le înconjura.

De ce nu pot să 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 folosind setările corecte, este posibil să aveți probleme atunci 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 nu este ceva pe care doriți să-l faceți pe fiecare computer în care vă duceți scripturile în jur - mai ales dacă unele dintre aceste computere nu sunt ale dvs.
  2. PowerShell nu permite execuția script-ului extern în mod implicit.
    Setarea ExecutionPolicy din PowerShell previne implicit execuția 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 în cazul unui cont la nivel de Administrator, trebuie să continuați să efectuați anumite acțiuni prin controlul contului de utilizator (UAC). Nu vrem să dezactivați acest lucru, dar este încă plăcut când putem să facem ceva mai ușor de rezolvat.
  4. Unii utilizatori pot avea personalizate medii PowerShell.
    Probabil că nu veți mai întâlni acest lucru frecvent, dar atunci 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 adresarea 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ă redenumiți fișierul batch pentru fiecare script sau de fiecare dată când mutați un script în jur, va folosi o variabilă de autoreferențiere pentru a construi calea fișierului pentru scriptul PowerShell. Pentru a face acest lucru, fișierul lot va trebui să fie plasat în același director ca și scriptul 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 lot:

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

Dacă nu ar exista alte restricții de securitate în loc, 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ă ecouarea comenzii. 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 într-o consolă goală, ca de obicei. De asemenea, puteți să o utilizați pentru a rula comenzi direct dintr-un fișier batch, incluzând parametrul -Command și argumentele corespunzătoare. Modul în care acest lucru este folosit pentru a viza fișierul .PS1 este cu variabila specială% ~ dpn0. Rulați dintr-un fișier batch,% ~ dpn0 este evaluat la litera unității, calea dosarului și numele fișierului (fără extensie) din fișierul lot. Deoarece fișierul batch și scriptul PowerShell vor fi în același folder și au același nume,% ~ dpn0.ps1 se va traduce pe 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 trecem prin testarea fiecărui 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ă când faceți dublu clic pe MyScript.bat.

Evident, scriptul PowerShell nu a rulat, dar asta e de așteptat - am rezolvat doar prima dintre cele patru probleme ale noastre, la urma urmei. Cu toate acestea, există câteva biți importanți demonstrat aici:

  1. Titlul ferestrei arată că scriptul de loturi a lansat cu succes PowerShell.
  2. Prima linie de ieșire arată că se utilizează un profil PowerShell personalizat. Aceasta este problema potențială # 4, menționată mai sus.
  3. Mesajul de eroare demonstrează restricțiile de executare în vigoare. 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 în mod corect scriptul PowerShell intenționat (D: \ Script Lab \ MyScript.ps1). Deci, cel puțin știm că lucrurile funcționează corect.

Profilul, în acest caz, este un script simplu dintr-o singură linie folosit 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 dvs. de profil:

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

Execuția politică din sistemul de testare este setată la RemoteSigned. Acest lucru permite execuția 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 scop demonstrativ, 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-vă pe ExecutionPolicy.

Noțiuni de bază în jurul setării ExecutionPolicy, de la CMD sau un script batch, este de fapt destul de ușor. Modificăm doar a doua linie a scriptului pentru a adăuga un alt parametru comenzii PowerShell.exe.

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

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

Acum că scriptul a fost executat corect, putem vedea ce face de fapt. Ne anunță că executăm scriptul ca utilizator limitat. Scriptul este, de fapt, rulat 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 care este folosit pentru demonstrație:

dacă [[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()) IsInRole ([Security.Principal.WindowsBuiltInRole] "Administrator")) Scriere-ieșire "Rularea ca Administrator! Write-Output 'Running Limited!' Pauză

De asemenea, veți observa că acum 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ă altitudine ș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 sări peste restul. 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 dintr-un fișier batch sau o sesiune CMD. Cu toate acestea, PowerShell ne permite să facem acest lucru cu Start-Process. Când este folosit cu argumentul "-Verb RunAs" în argumentele sale, Start-Process va încerca să lanseze o aplicație cu permisiuni de administrator. Dacă sesiunea PowerShell nu este deja ridicată, aceasta va declanșa o solicitare UAC. Pentru a utiliza acest lucru din fișierul batch pentru a lansa scriptul nostru, vom termina de reproducere 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țiePolitică 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 nota de script de profil. Apoi, MyScript.ps1 rulează și vedem că suntem cu adevărat într-o sesiune ridicată.

Și acolo e 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 vedea dacă au apărut erori în primul rând în PowerShell.

Pasul 4: Obținerea profilelor personalizate PowerShell.

Să scăpăm de notificarea profundă a profilului vostru acum, nu? Aici, nu este chiar o provocare, dar dacă profilul PowerShell al unui utilizator modifică setările implicite, variabilele sau funcțiile în moduri pe care probabil că nu le-ați anticipat cu scenariul dvs., acestea pot fi cu adevărat supărătoare. 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 încă o dată al doilea rând al fișierului batch:

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

Adăugarea parametrului -NoProfile la ambele instanțe ale PowerShell care sunt lansate de script înseamnă că scriptul de profil al utilizatorului va fi complet ocolit în ambii pași și că 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 face acest lucru fără a doua instanță PowerShell, iar a doua linie a fișierului dvs. batch ar trebui să arate astfel:

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

Rezultatul va arăta astfel:

(Desigur, pentru scripturile non-Administrator, ai putea să faci pauză de sfârșit de script în scriptul dvs. PowerShell și î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 dacă aveți sau nu nevoie de permisiuni de administrator pentru scriptul dvs. PowerShell (și nu ar trebui să le cereți dacă nu), fișierul final de lot ar trebui să arate ca unul din cele două.

Fără acces Admin:

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

Cu acces Admin:

@CHO OFF PowerShell.exe -NoProfile -Command "& Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecuțiePolitica 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ă distrați cu oricare dintre setările de securitate de pe sistem. 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 în legătură cu revenirea la schimbări mai târziu.

Referințe:

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