Hemsida » hur » Så här använder du en batchfil för att göra PowerShell-skript enklare att köra

    Så här använder du en batchfil för att göra PowerShell-skript enklare att köra

    Av flera anledningar är mestadels säkerhetsrelaterade, PowerShell-skript inte lika lättportabla och användbara som batchskript kan vara. Vi kan dock kombinera ett batch-skript med våra PowerShell-skript för att arbeta runt dessa problem. Här visar vi några av dessa problemområden, och hur man bygger ett batchskript för att komma runt dem.

    Varför kan jag inte bara kopiera min .PS1-fil till en annan dator och köra den?

    Om inte målsystemet är förkonfigurerat för att tillåta körning av godtyckliga skript, med de nödvändiga behörigheterna och med rätt inställningar, är risken att du kommer att stöta på några problem när du försöker göra det här.

    1. PowerShell är inte associerat med .PS1 filtillägg som standard.
      Vi tog upp det här först i vår PowerShell Geek School-serie. Windows associerar .PS1-filer till Anteckningar som standard istället för att skicka dem till PowerShell-kommandotolken. Det här för att förhindra oavsiktligt utförande av skadliga skript genom att helt enkelt dubbelklicka på dem. Det finns sätt att ändra detta beteende, men det är nog inte något du vill göra på varje dator som du bär dina skript runt - särskilt om några av dessa datorer inte är dina egna.
    2. PowerShell tillåter inte externt manusutförande.
      Exekveringspolicy-inställningen i PowerShell förhindrar att externa skript utförs som standard i alla versioner av Windows. I vissa Windows-versioner tillåter standard inte alls att skriptet körs. Vi visade dig hur du ändrar inställningen i Så här låter du utföra PowerShell-skript på Windows 7. Det här är också något du inte vill göra på bara vilken dator som helst.
    3. Vissa PowerShell-skript fungerar inte utan administratörsbehörigheter.
      Även med ett administratörsnivåkonto behöver du fortfarande komma igenom användarkontokontroll (UAC) för att utföra vissa åtgärder. Vi vill inte inaktivera det här, men det är fortfarande trevligt när vi kan göra det lite lättare att hantera.
    4. Vissa användare kan ha anpassade PowerShell-miljöer.
      Du kommer antagligen inte att köra in i det här ofta, men när du gör det kan det vara lustigt att felsöka och felsöka dina skript lite frustrerande. Lyckligtvis kan vi komma runt detta utan att göra några permanenta förändringar också.

    Steg 1: Dubbelklicka för att köra.

    Låt oss börja med att ta itu med det första problemet - .PS1-filföreningar. Du kan inte dubbelklicka för att köra .PS1-filer, men du kan utföra en .BAT-fil på det sättet. Så ska vi skriva en batchfil för att ringa PowerShell-skriptet från kommandoraden för oss.

    Så vi behöver inte skriva om batchfilen för varje skript, eller varje gång vi flyttar ett skript runt, kommer det att använda sig av en självreferensvariabel för att bygga filbanan för PowerShell-skriptet. För att göra detta arbete måste batchfilen placeras i samma mapp som ditt PowerShell-skript och har samma filnamn. Så om ditt PowerShell-skript kallas "MyScript.ps1", vill du namnge din batchfil "MyScript.bat" och se till att det finns i samma mapp. Lägg sedan dessa linjer i batch-scriptet:

    @ECHO AV PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE

    Om det inte fanns andra säkerhetsrestriktioner på plats, skulle det verkligen vara allt som krävs för att köra ett PowerShell-skript från en batchfil. Faktum är att de första och sista linjerna bara är en fråga om preferens - det är den andra raden som verkligen gör jobbet. Här är nedbrytningen:

    @ECHO OFF stänger av kommando-ekko. Detta håller bara dina andra kommandon från att visas på skärmen när batchfilen körs. Denna rad är själv gömd genom att använda symbolen vid (@) framför den.

    PowerShell.exe -Command "& '% ~ dpn0.ps1'" driver faktiskt PowerShell-skriptet. PowerShell.exe kan givetvis kallas från ett CMD-fönster eller en batchfil för att starta PowerShell till en rak konsol som vanligt. Du kan också använda den för att köra kommandon direkt från en batchfil, genom att inkludera parametern -Command och lämpliga argument. Så här används detta för att rikta in vår .PS1-fil med den speciella% ~ dpn0-variabeln. Kör från en batchfil utvärderas% ~ dpn0 till enhetens brev, mappväg och filnamn (utan tillägg) i batchfilen. Eftersom batchfilen och PowerShell-skriptet kommer att ligga i samma mapp och ha samma namn, kommer% ~ dpn0.ps1 att översättas till hela filbanan i PowerShell-skriptet.

    PAUS pausar bara batchexekveringen och väntar på användarinmatning. Det här är vanligtvis användbart att ha i slutet av dina batchfiler, så att du får chansen att granska någon kommandoutmatning innan fönstret försvinner. När vi går igenom test av varje steg kommer användbarheten av detta att bli tydligare.

    Så är den grundläggande batchfilen konfigurerad. För demonstration sparas den här filen som "D: \ Script Lab \ MyScript.bat" och det finns en "MyScript.ps1" i samma mapp. Låt oss se vad som händer när vi dubbelklickar på MyScript.bat.

    Självklart körde inte PowerShell-skriptet, men det kan man förvänta sig - vi har trots allt bara behandlat det första av våra fyra problem. Det finns dock några viktiga punkter som visas här:

    1. Fönstertiteln visar att batchskriptet framgångsrikt startade PowerShell.
    2. Den första produktionslinjen visar att en anpassad PowerShell-profil används. Detta är potentiellt problem # 4, listat ovan.
    3. Felmeddelandet demonstrerar ExecutionPolicy-begränsningar i kraft. Det är vårt problem # 2.
    4. Den understrukna delen av felmeddelandet (som är gjort native av PowerShells felutgång) visar att batchskriptet riktades in riktigt mot det avsedda PowerShell-skriptet (D: \ Script Lab \ MyScript.ps1). Så vi vet åtminstone att mycket fungerar bra.

    Profilen, i det här fallet, är ett enkelt enstegsskript som används för denna demonstration för att generera output när profilen är aktiv. Du kan anpassa din egen PowerShell-profil för att göra det även om du vill testa dessa skript själv. Lägg bara till följande rad i ditt profilskript:

    Skriv ut "Custom PowerShell-profilen i kraft!"

    ExecutionPolicy på testsystemet här är inställt på RemoteSigned. Detta möjliggör utförande av skript som skapats lokalt (som profilskriptet), medan blockering av skript från externa källor om de inte är signerade av en betrodd myndighet. För demonstrationsändamål användes följande kommando för att flagga MyScript.ps1 som från en extern källa:

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

    Det sätter Zone.Identifier alternativ dataströmmen på MyScript.ps1 så att Windows kommer att tro att filen kom från Internet. Det kan enkelt vändas med följande kommando:

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

    Steg 2: Ta dig runt ExecutionPolicy.

    Att komma runt inställningen ExecutionPolicy, från CMD eller en batch script, är faktiskt ganska lätt. Vi ändrar bara den andra raden av manuset för att lägga till en ytterligare parameter i PowerShell.exe-kommandot.

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

    Parametern -ExecutionPolicy kan användas för att ändra ExecutionPolicy som används när du hämtar en ny PowerShell-session. Detta kommer inte att fortsätta utöver den sessionen, så vi kan köra PowerShell så här närhelst vi behöver utan att försämra systemets allmänna säkerhetsställning. Nu när vi har fixat det, låt oss få en annan gå till det:

    Nu när manuset har utförts korrekt kan vi se vad det egentligen gör. Det låter oss veta att vi kör skriptet som en begränsad användare. Skriptet körs faktiskt av ett konto med administratörsbehörigheter, men användarkontokontrollen kommer i vägen. Även om detaljer om hur man letar efter skriptet för administratörsbehörighet ligger utanför ramen för den här artikeln, här är koden som används för demonstration:

    om (([Säkerhet.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()). IsInRole ([Security.Principal.WindowsBuiltInRole] "Administratör")) Skrivutskrift 'Kör som administratör!' else Skriv ut "Running Limited! ' Paus

    Du märker också att det nu finns två "Pause" -operationer i skriptutmatningen - en från PowerShell-skriptet och en från batchfilen. Anledningen till detta kommer att bli tydligare i nästa steg.

    Steg 3: Få administratörsbehörighet.

    Om ditt skript inte kör några kommandon som kräver höjning, och du är ganska säker på att du inte behöver oroa dig för att någons anpassade profiler kommer i vägen, kan du hoppa över resten av detta. Om du kör några cmdlets administratörsnivå behöver du den här biten.

    Tyvärr finns det inget sätt att utlösa UAC för höjning från en batchfil eller CMD-session. PowerShell tillåter dock oss att göra detta med Start-Process. När det används med "-Verb RunAs" i sina argument, försöker Start-Process att starta ett program med administratörsbehörigheter. Om PowerShell-sessionen inte redan är förhöjd kommer detta att utlösa en UAC-prompt. För att använda detta från batchfilen för att starta vårt skript kommer vi att sluta gyta två PowerShell-processer - en för att avaktivera Start-Process och en annan, lanserad av Start-Process, för att köra skriptet. Den andra raden i batchfilen måste ändras till följande:

    PowerShell.exe-kommandot "& Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"

    När batchfilen körs, kommer den första raden av utdata som vi ser är från PowerShell-profilskriptet. Då kommer det att finnas en UAC-prompt när Start-Process försöker starta MyScript.ps1.

    Efter att ha klickat i UAC-prompten kommer en ny PowerShell-instans att hälla. Eftersom det här är en ny instans, kommer vi naturligtvis igen att se profilskriptmeddelandet. Sedan kör MyScript.ps1 och vi ser att vi verkligen är i en förhöjd session.

    Och det är anledningen till att vi har två pauser här också. Om inte för den i PowerShell-skriptet så skulle vi aldrig se skriptets utdata - PowerShell-fönstret skulle bara dyka upp och försvinna så snart skriptet är klart. Och utan pausen i batchfilen kunde vi inte se om det fanns några fel som startade PowerShell i första hand.

    Steg 4: Ta bort egna PowerShell-profiler.

    Låt oss bli av med det dåliga anpassade profilmeddelandet nu ska vi? Här är det knappast till och med en olägenhet, men om en användares PowerShell-profil ändrar standardinställningar, variabler eller funktioner på sätt som du kanske inte har förväntat sig med ditt skript, kan de vara mycket besvärliga. Det är mycket enklare att köra ditt skript utan profilen helt, så du behöver inte oroa dig för det här. För att göra det behöver vi bara ändra den andra raden i batchfilen en gång till:

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

    Lägga till -NoProfil-parametern i båda instanserna av PowerShell som lanseras av manuset innebär att användarens profilskript helt kommer att förbigås i båda stegen och vårt PowerShell-skript körs i en ganska förutsägbar standardmiljö. Här kan du se att det inte finns något anpassat profilmeddelande i någon av de spridda skalen.

    Om du inte behöver administratörsrättigheter i ditt PowerShell-skript och du har hoppat över steg 3 kan du göra utan den andra PowerShell-förekomsten och den andra raden i din batchfil ska se ut så här:

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

    Utgången kommer då att se ut så här:

    (För icke-administratörskript kan du självklart utan att göra en paus i ditt PowerShell-skript även här eftersom allt är fångat i samma konsolfönster och skulle hållas där med pausen i slutet av batchfilen ändå.)

    Slutförda satsvisa filer.

    Beroende på om du behöver administratörsbehörigheter för ditt PowerShell-skript (och du borde verkligen inte begära dem om du inte gör det) ska den sista batchfilen se ut som en av de två nedan.

    Utan administratörsbehörighet:

    @ECHO AV PowerShell.exe -NoProfile -ExecutionPolicy Bypass-Kommando "& '% ~ dpn0.ps1'" PAUSE

    Med Admin-åtkomst:

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

    Kom ihåg att lägga batchfilen i samma mapp som PowerShell-skriptet du vill använda det för, och ge det samma namn. Då, oavsett vilket system du tar dessa filer till, kan du köra ditt PowerShell-skript utan att behöva krossa med någon av säkerhetsinställningarna på systemet. Du kan säkert göra dessa ändringar manuellt varje gång, men det sparar dig det besväret och du behöver inte oroa dig för att återställa ändringarna senare.


    referenser:

    • Running PowerShell-skript från en batchfil - Daniel Schroeders Programmeringsblogg
    • Kontrollera efter administratörsbehörigheter i PowerShell - Hej, Scripting Guy! blogg