Startpagina » hoe » Een batchbestand gebruiken om PowerShell-scripts gemakkelijker te laten werken

    Een batchbestand gebruiken om PowerShell-scripts gemakkelijker te laten werken

    Om verschillende redenen zijn PowerShell-scripts meestal beveiligingsgerelateerd en daarom niet zo gemakkelijk draagbaar en bruikbaar als batch-scripts. We kunnen echter een batch-script bundelen met onze PowerShell-scripts om deze problemen te omzeilen. Hier laten we u een paar van die probleemgebieden zien en hoe u een batchtypen kunt bouwen om ze te omzeilen.

    Waarom kan ik mijn .PS1-bestand niet kopiëren naar een andere computer en het uitvoeren?

    Tenzij het doelsysteem vooraf is geconfigureerd voor het uitvoeren van willekeurige scripts, met de vereiste rechten en het gebruiken van de juiste instellingen, is de kans groot dat u een aantal problemen tegenkomt wanneer u dit probeert te doen.

    1. PowerShell is standaard niet gekoppeld aan de extensie .PS1.
      We brachten dit eerst naar voren in onze PowerShell Geek School-serie. Windows koppelt .PS1-bestanden standaard aan Kladblok in plaats van deze naar de PowerShell-opdrachtinterpreter te verzenden. Dit is om onbedoelde uitvoering van kwaadwillende scripts te voorkomen door er eenvoudig op te dubbelklikken. Er zijn manieren waarop je dit gedrag kunt veranderen, maar het is waarschijnlijk niet iets dat je wilt doen op elke computer waar je je scripts naartoe draagt ​​- vooral als sommige van die computers niet van jou zijn.
    2. PowerShell staat standaard geen externe scriptuitvoering toe.
      De ExecutionPolicy-instelling in PowerShell voorkomt dat standaard externe scripts worden uitgevoerd in alle versies van Windows. In sommige Windows-versies staat de standaard helemaal geen uitvoering van scripts toe. We hebben u laten zien hoe u deze instelling kunt wijzigen in Hoe u de uitvoering van PowerShell-scripts op Windows 7 kunt toestaan. Dit is echter ook iets dat u niet op elke computer wilt doen..
    3. Sommige PowerShell-scripts werken niet zonder beheerdersmachtigingen.
      Zelfs als u met een account op beheerdersniveau werkt, moet u nog steeds Gebruikersaccountbeheer (UAC) doorlopen om bepaalde acties uit te voeren. We willen dit niet uitschakelen, maar het is nog steeds leuk als we het een beetje makkelijker kunnen maken om ermee om te gaan.
    4. Sommige gebruikers hebben mogelijk aangepaste PowerShell-omgevingen.
      Je zult dit waarschijnlijk niet vaak tegenkomen, maar als je dit doet, kan het draaien en het oplossen van problemen met je scripts een beetje frustrerend zijn. Gelukkig kunnen we dit omzeilen zonder ook maar enige permanente wijzigingen aan te brengen.

    Stap 1: Dubbelklik om uit te voeren.

    Laten we beginnen met het aanpakken van het eerste probleem - .PS1 bestandsassociaties. U kunt niet dubbelklikken om .PS1-bestanden uit te voeren, maar u kunt op die manier een .bat-bestand uitvoeren. We zullen dus een batchbestand schrijven om het PowerShell-script vanaf de opdrachtregel voor ons te bellen.

    We hoeven het batchbestand niet opnieuw te schrijven voor elk script, of elke keer dat we een script verplaatsen, maakt het gebruik van een zelfverwezen variabele om het bestandspad voor het PowerShell-script te bouwen. Om dit te laten werken, moet het batchbestand in dezelfde map als uw PowerShell-script worden geplaatst en dezelfde bestandsnaam hebben. Dus als uw PowerShell-script "MyScript.ps1" wordt genoemd, moet u uw batchbestand "MyScript.bat" een naam geven en ervoor zorgen dat het zich in dezelfde map bevindt. Plaats vervolgens deze regels in het batch-script:

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

    Als het niet om de andere beveiligingsbeperkingen zou gaan, zou dat echt het enige zijn dat nodig is om een ​​PowerShell-script vanuit een batchbestand uit te voeren. In feite zijn de eerste en laatste regels hoofdzakelijk een kwestie van voorkeur - het is de tweede regel die het werk echt doet. Dit is de verdeling:

    @ECHO OFF schakelt commando echoën uit. Hierdoor blijven alleen uw andere opdrachten op het scherm zichtbaar wanneer het batchbestand wordt uitgevoerd. Deze lijn is zelf verborgen door het symbool er vóór (@) voor te gebruiken.

    PowerShell.exe -Command "& '% ~ dpn0.ps1' ' voert in feite het PowerShell-script uit. PowerShell.exe kan natuurlijk worden gebeld vanuit elk CMD-venster of batchbestand om PowerShell te starten naar een kale console zoals gewoonlijk. U kunt het ook gebruiken om opdrachten rechtstreeks vanuit een batchbestand uit te voeren, door de -Command-parameter en de juiste argumenten op te nemen. De manier waarop dit wordt gebruikt om ons .PS1-bestand te targeten, is met de speciale variabele% ~ dpn0. Uitvoeren van een batchbestand,% ~ dpn0 evalueert naar de stationsaanduiding, mappad en bestandsnaam (zonder extensie) van het batchbestand. Omdat het batchbestand en het PowerShell-script zich in dezelfde map bevinden en dezelfde naam hebben, vertaalt% ~ dpn0.ps1 naar het volledige pad naar het PowerShell-script.

    PAUZE pauzeert gewoon de batchuitvoering en wacht op gebruikersinvoer. Dit is over het algemeen handig om aan het einde van uw batchbestanden te hebben, zodat u de mogelijkheid hebt om elke opdrachtuitvoer te beoordelen voordat het venster verdwijnt. Terwijl we elke stap van het testen doorlopen, zal het nut hiervan duidelijker worden.

    Het basisbatchbestand is dus ingesteld. Voor demonstratiedoeleinden wordt dit bestand opgeslagen als "D: \ Script Lab \ MyScript.bat" en staat er een "MyScript.ps1" in dezelfde map. Laten we eens kijken wat er gebeurt als we dubbelklikken op MyScript.bat.

    Natuurlijk is het PowerShell-script niet uitgevoerd, maar dat is te verwachten - we hebben tenslotte alleen de eerste van onze vier problemen aangepakt. Er zijn hier echter enkele belangrijke dingen aangetoond:

    1. De titel van het venster laat zien dat het batchtype met succes PowerShell heeft gestart.
    2. De eerste regel uitvoer geeft aan dat een aangepast PowerShell-profiel in gebruik is. Dit is potentieel probleem # 4, hierboven vermeld.
    3. In het foutbericht worden de ExecutionPolicy-beperkingen van kracht. Dat is ons probleem # 2.
    4. Het onderstreepte gedeelte van het foutbericht (dat native wordt uitgevoerd door de uitvoer van PowerShell) toont dat het batchty script het beoogde PowerShell-script correct had gericht (D: \ Script Lab \ MyScript.ps1). Dus we weten tenminste dat veel goed werkt.

    Het profiel is in dit geval een eenvoudig script van één regel dat voor deze demonstratie wordt gebruikt om uitvoer te genereren wanneer het profiel actief is. U kunt ook uw eigen PowerShell-profiel aanpassen om dit te doen, als u deze scripts zelf wilt testen. Voeg eenvoudig de volgende regel toe aan uw profielscript:

    Write-Output 'Eigen PowerShell-profiel van kracht!'

    De ExecutionPolicy op het testsysteem hier is ingesteld op RemoteSigned. Hiermee kunnen scripts lokaal worden gemaakt (zoals het profielscript), terwijl scripts van externe bronnen worden geblokkeerd, tenzij ze zijn ondertekend door een vertrouwde instantie. Voor demonstratiedoeleinden werd de volgende opdracht gebruikt om MyScript.ps1 te markeren als afkomstig van een externe bron:

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

    Dat zet de Alternatieve gegevensstroom Zone.Identifier op MyScript.ps1, zodat Windows denkt dat het bestand afkomstig is van het internet. Het kan eenvoudig worden omgekeerd met het volgende commando:

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

    Stap 2: Kennismaken met ExecutionPolicy.

    Het is vrij eenvoudig om de ExecutionPolicy-instelling te doorlopen, van CMD of een batch-script. We wijzigen gewoon de tweede regel van het script om nog een parameter toe te voegen aan de opdracht PowerShell.exe.

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

    De parameter -ExecutionPolicy kan worden gebruikt om de uitvoeringPolicy aan te passen die wordt gebruikt wanneer u een nieuwe PowerShell-sessie maakt. Dit duurt niet langer dan die sessie, dus we kunnen PowerShell zo draaien wanneer we dat nodig hebben zonder de algemene beveiligingshouding van het systeem te verzwakken. Nu we dat hebben opgelost, laten we er nog een keer tegenaan:

    Nu het script correct is uitgevoerd, kunnen we zien wat het daadwerkelijk doet. Het laat ons weten dat we het script uitvoeren als een beperkte gebruiker. Het script wordt in feite uitgevoerd door een account met beheerdersrechten, maar gebruikersaccountbeheer staat in de weg. Hoewel details over hoe het script controleert of beheerders toegang hebben buiten het bestek van dit artikel vallen, is hier de code die wordt gebruikt voor demonstratie:

    if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()). IsInRole ([Security.Principal.WindowsBuiltInRole] "Administrator")) Write-Output 'Running as Administrator!' else Write-Output 'Running Limited!' Pauze

    U zult ook merken dat er nu twee "Pauze" -bewerkingen zijn in de scriptuitvoer - een uit het PowerShell-script en een uit het batchbestand. De reden hiervoor zal in de volgende stap duidelijker worden.

    Stap 3: Beheerderstoegang krijgen.

    Als uw script geen opdrachten uitvoert die een hoogte vereisen, en u bent er vrij zeker van dat u zich geen zorgen hoeft te maken dat iemands aangepaste profielen in de weg zitten, kunt u de rest hiervan overslaan. Als u echter enkele cmdlets op beheerdersniveau gebruikt, hebt u dit stuk nodig.

    Helaas is er geen manier om UAC te activeren voor elevatie vanuit een batchbestand of CMD-sessie. PowerShell staat ons echter wel toe om dit te doen met Start-Process. Bij gebruik in combinatie met "-Verb RunAs" probeert Start-Process een toepassing te starten met beheerdersrechten. Als de PowerShell-sessie nog niet is verhoogd, wordt er een UAC-prompt geactiveerd. Om dit vanuit het batchbestand te gebruiken voor het starten van ons script, zullen we uiteindelijk twee PowerShell-processen opstarten - een om Start-Process af te vuren en een andere, gestart door Start-Process, om het script uit te voeren. De tweede regel van het batchbestand moet hier worden gewijzigd:

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

    Wanneer het batchbestand wordt uitgevoerd, is de eerste regel uitvoer die wordt weergegeven, afkomstig uit het PowerShell-profielscript. Er zal dan een UAC-prompt verschijnen wanneer Start-Process MyScript.ps1 probeert te starten.

    Nadat u op de UAC-prompt heeft geklikt, wordt een nieuwe PowerShell-instantie gemaakt. Omdat dit een nieuw exemplaar is, zien we natuurlijk opnieuw het profielscript. Vervolgens wordt MyScript.ps1 uitgevoerd en we zien dat we inderdaad in een verhoogde sessie zitten.

    En er is de reden dat we hier ook twee pauzes hebben. Als dat niet het geval is in het PowerShell-script, zien we nooit de uitvoer van het script: het PowerShell-venster verschijnt gewoon en verdwijnt zodra het script is voltooid. En zonder de pauze in het batchbestand kunnen we niet zien of er fouten zijn opgetreden bij het starten van PowerShell in de eerste plaats.

    Stap 4: Aangepaste PowerShell-profielen verkennen.

    Laten we ons nu van die vervelende aangepaste profielbekendheid ontdoen, nietwaar? Hier is het nauwelijks hinderlijk, maar als het PowerShell-profiel van een gebruiker de standaardinstellingen, variabelen of functies wijzigt op manieren die je misschien niet hebt verwacht met je script, kunnen ze erg lastig zijn. Het is veel eenvoudiger om uw script zonder het profiel uit te voeren, zodat u zich hier geen zorgen over hoeft te maken. Om dat te doen, hoeven we alleen maar de tweede regel van het batchbestand nog een keer te wijzigen:

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

    Door de parameter -NoProfile aan beide exemplaren van PowerShell toe te voegen die door het script worden gestart, wordt in beide stappen het profielscript van de gebruiker volledig omzeild en wordt ons PowerShell-script uitgevoerd in een redelijk voorspelbare, standaardomgeving. Hier kun je zien dat er geen aangepast profielbericht is in een van de spawn-shells.

    Als u geen beheerdersrechten in uw PowerShell-script nodig hebt en stap 3 hebt overgeslagen, kunt u het doen zonder de tweede PowerShell-instantie en de tweede regel van uw batchbestand er als volgt uitzien:

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

    De uitvoer ziet er dan als volgt uit:

    (Natuurlijk, voor niet-beheerdersscripts, zou je op dit moment ook zonder een einde-van-scriptpauze in je PowerShell-script kunnen doen, omdat alles in hetzelfde consolevenster wordt vastgelegd en daar aan het einde van de pauze door de pauze wordt vastgehouden het batchbestand toch.)

    Voltooide batchbestanden.

    Afhankelijk van het feit of u beheerdersbevoegdheden nodig hebt voor uw PowerShell-script (en u zou het eigenlijk niet moeten vragen als u dit niet doet), zou het uiteindelijke batchbestand eruit moeten zien als een van de onderstaande twee.

    Zonder beheerderstoegang:

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

    Met beheerderstoegang:

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

    Vergeet niet om het batchbestand in dezelfde map te plaatsen als het PowerShell-script waarvoor u het wilt gebruiken en geef het dezelfde naam. Vervolgens maakt het niet uit naar welk systeem u deze bestanden meeneemt, u kunt uw PowerShell-script uitvoeren zonder dat u zich hoeft bezig te houden met de beveiligingsinstellingen op het systeem. Je kunt die wijzigingen zeker elke keer handmatig doen, maar dit bespaart je problemen en je hoeft je geen zorgen te maken over het later terugdraaien van de wijzigingen.


    Referenties:

    • PowerShell-scripts uitvoeren vanuit een batchbestand - het programmeerblog van Daniel Schroeder
    • Controleren op beheerdersrechten in PowerShell - Hey, Scripting Guy! blog