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.
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.
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:
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 "
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.
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.
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.)
Î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: