9Sep
Aus mehreren Gründen sind meist sicherheitsrelevante PowerShell-Skripts nicht so leicht portierbar und verwendbar wie Batch-Skripte. Um diese Probleme zu umgehen, können wir jedoch ein Batch-Skript mit unseren PowerShell-Skripts bündeln. Hier zeigen wir Ihnen einige dieser Problembereiche und wie Sie ein Batch-Skript erstellen, um sie zu umgehen.
Warum kann ich meine. PS1-Datei nicht einfach auf einen anderen Computer kopieren und ausführen?
Sofern das Zielsystem nicht vorkonfiguriert wurde, um das Ausführen von beliebigen Skripten mit den erforderlichen Rechten und den richtigen Einstellungen zu ermöglichen, werden Sie wahrscheinlich einige Probleme bekommen, wenn Sie dies versuchen.
- PowerShell ist standardmäßig nicht mit der Dateierweiterung. PS1 verknüpft.
Wir haben dies zunächst in unserer PowerShell Geek School-Serie vorgestellt. Windows ordnet. PS1-Dateien standardmäßig dem Editor zu, anstatt sie an den PowerShell-Befehlsinterpreter zu senden. Dies soll verhindern, dass bösartige Skripts versehentlich ausgeführt werden, indem Sie einfach auf sie doppelklicken. Es gibt Möglichkeiten, dieses Verhalten zu ändern, aber es ist wahrscheinlich nicht das, was Sie auf jedem Computer, mit dem Sie Ihre Skripts herumtragen, tun möchten - vor allem, wenn einige dieser Computer nicht Ihre eigenen sind. - PowerShell lässt standardmäßig keine externe Skriptausführung zu.
Die Einstellung ExecutionPolicy in PowerShell verhindert die Ausführung externer Skripts standardmäßig in allen Windows-Versionen. In einigen Windows-Versionen erlaubt der Standard überhaupt keine Skriptausführung. Wir haben Ihnen gezeigt, wie Sie diese Einstellung unter Ausführen von PowerShell-Skripts unter Windows 7 ändern können. Dies ist jedoch auch etwas, das Sie nicht auf einem beliebigen Computer ausführen möchten. - Einige PowerShell-Skripts funktionieren nicht ohne Administratorrechte.
Selbst wenn Sie mit einem Konto auf Administratorebene ausgeführt werden, müssen Sie die Benutzerkontensteuerung( User Account Control, UAC) noch ausführen, um bestimmte Aktionen auszuführen. Wir wollen das nicht deaktivieren, aber es ist immer noch schön, wenn wir es etwas einfacher machen können. - Einige Benutzer haben möglicherweise angepasste PowerShell-Umgebungen.
Sie werden wahrscheinlich nicht oft darauf stoßen, aber wenn Sie es tun, kann das Laufen und die Fehlersuche in Ihren Skripten etwas frustrierend sein. Glücklicherweise können wir das auch ohne bleibende Veränderungen schaffen.
Schritt 1: Zum Ausführen doppelklicken.
Beginnen wir mit dem ersten Problem -. PS1-Dateizuordnungen. Sie können nicht doppelklicken, um. PS1-Dateien auszuführen, aber Sie können eine. BAT-Datei auf diese Weise ausführen. Wir schreiben also eine Batch-Datei, um das PowerShell-Skript über die Befehlszeile für uns aufzurufen.
Daher müssen wir die Batch-Datei nicht für jedes Skript neu schreiben, oder jedes Mal, wenn wir ein Skript verschieben, wird eine selbstreferenzierende Variable verwendet, um den Dateipfad für das PowerShell-Skript zu erstellen. Damit dies funktioniert, muss die Batch-Datei im selben Ordner wie das PowerShell-Skript gespeichert werden und denselben Dateinamen haben. Wenn Ihr PowerShell-Skript also "MyScript.ps1" heißt, sollten Sie Ihre Batch-Datei "MyScript.bat" benennen und sicherstellen, dass sie sich im selben Ordner befindet. Dann setzen Sie diese Zeilen in das Batch-Skript:
@ECHO OFF PowerShell.exe -Kommando "& '% ~ dpn0.ps1'" PAUSEWenn es nicht für die anderen Sicherheitsbeschränkungen vorhanden wäre, wäre das wirklich allesEs dauert ein PowerShell-Skript aus einer Batch-Datei auszuführen. Tatsächlich sind die erste und die letzte Zeile hauptsächlich eine Frage der Präferenz - es ist die zweite Zeile, die wirklich die Arbeit macht. Hier ist der Zusammenbruch:
@ECHO OFF schaltet das Befehlsechoing aus. Dadurch werden Ihre anderen Befehle nicht mehr auf dem Bildschirm angezeigt, wenn die Stapelverarbeitungsdatei ausgeführt wird. Diese Zeile wird selbst durch das Symbol at( @) davor verborgen.
PowerShell.exe - Befehl "&'% ~ Dpn0.ps1' " führt das PowerShell-Skript aus. PowerShell.exe kann natürlich von jedem CMD-Fenster oder jeder Batch-Datei aus aufgerufen werden, um PowerShell wie üblich auf einer leeren Konsole zu starten. Sie können es auch verwenden, um Befehle direkt aus einer Stapeldatei auszuführen, indem Sie den Parameter -Command und die entsprechenden Argumente einfügen. Die Art, wie dies verwendet wird, um auf unsere. PS1-Datei zu zielen, ist die spezielle Variable% ~ dpn0.Aus einer Batch-Datei ausgeführt, ermittelt% ~ dpn0 den Laufwerksbuchstaben, den Ordnerpfad und den Dateinamen( ohne Erweiterung) der Batch-Datei. Da sich die Batch-Datei und das PowerShell-Skript im selben Ordner befinden und denselben Namen haben, wird% ~ dpn0.ps1 in den vollständigen Dateipfad des PowerShell-Skripts übersetzt.
PAUSE unterbricht lediglich die Stapelverarbeitung und wartet auf Benutzereingaben. Dies ist im Allgemeinen nützlich, um am Ende Ihrer Batch-Dateien zu haben, so dass Sie die Möglichkeit haben, alle Befehlsausgaben zu überprüfen, bevor das Fenster verschwindet. Wenn wir jeden Schritt testen, wird der Nutzen davon deutlicher.
So, die grundlegende Batch-Datei ist eingerichtet. Zu Demonstrationszwecken wird diese Datei als "D: \ Script Lab \ MyScript.bat" gespeichert und es befindet sich ein "MyScript.ps1" im selben Ordner. Mal sehen, was passiert, wenn wir auf MyScript.bat doppelklicken.
Offensichtlich lief das PowerShell-Skript nicht, aber das ist zu erwarten - wir haben schließlich nur das erste unserer vier Probleme angesprochen. Es werden jedoch einige wichtige Bits hier demonstriert:
- Der Fenstertitel zeigt, dass das Stapelscript PowerShell erfolgreich gestartet hat.
- Die erste Zeile der Ausgabe zeigt, dass ein benutzerdefiniertes PowerShell-Profil verwendet wird. Dies ist das potentielle Problem Nr. 4, das oben aufgeführt ist.
- Die Fehlermeldung zeigt die aktuellen Ausführungspolicy-Einschränkungen an. Das ist unser Problem # 2.
- Der unterstrichene Teil der Fehlermeldung( der nativ durch die PowerShell-Fehlerausgabe erfolgt) zeigt, dass das Stapelscript das beabsichtigte PowerShell-Skript( D: \ Script Lab \ MyScript.ps1) korrekt ausgerichtet hat. So wissen wir zumindest, dass vieles richtig funktioniert.
Das Profil ist in diesem Fall ein einfaches einzeiliges Skript, das für diese Demonstration verwendet wird, um die Ausgabe zu generieren, wenn das Profil aktiv ist. Sie können auch Ihr eigenes PowerShell-Profil anpassen, wenn Sie diese Skripts selbst testen möchten. Fügen Sie Ihrem Profilskript einfach die folgende Zeile hinzu:
Write-Output 'Custom PowerShell profile in effect!'Die ExecutionPolicy auf dem Testsystem ist hier auf RemoteSigned gesetzt. Dies ermöglicht die Ausführung von Skripten, die lokal erstellt werden( wie das Profilskript), während Skripts von externen Quellen blockiert werden, sofern sie nicht von einer vertrauenswürdigen Autorität signiert sind. Zu Demonstrationszwecken wurde der folgende Befehl verwendet, um MyScript.ps1 als aus einer externen Quelle zu kennzeichnen:
Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Wert "[ZoneTransfer]` nZoneId = 3 "-Stream 'Zone. Identifier'Dadurch wird der alternative Datenstrom von Zone. Identifier auf MyScript.ps1 gesetzt, sodass Windows denkt, dass die Datei aus dem Internet stammt. Es kann leicht mit dem folgenden Befehl rückgängig gemacht werden:
Clear-Content -Pfad 'D: \ Skriptlab \ MyScript.ps1' -Stream 'Zone. Identifier'Schritt 2: Getting ExecutionPolicy.
Die Ausführung der ExecutionPolicy-Einstellung von CMD oder einem Batch-Skript aus ist ziemlich einfach. Wir ändern nur die zweite Zeile des Skripts, um dem Befehl PowerShell.exe einen weiteren Parameter hinzuzufügen.
PowerShell.exe -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"Mit dem Parameter -ExecutionPolicy kann die Ausführungspolicy geändert werden, die beim Erstellen einer neuen PowerShell-Sitzung verwendet wird. Dies wird nicht über diese Sitzung hinaus bestehen bleiben, so dass wir PowerShell jederzeit ausführen können, ohne die allgemeine Sicherheit des Systems zu beeinträchtigen. Nun, da wir das Problem behoben haben, wollen wir es noch einmal versuchen:
Nun, da das Skript ordnungsgemäß ausgeführt wurde, können wir sehen, was es tatsächlich tut. Es teilt uns mit, dass wir das Skript als eingeschränkter Benutzer ausführen. Das Skript wird tatsächlich von einem Konto mit Administratorberechtigungen ausgeführt, aber die Benutzerkontensteuerung stört den Weg. Obwohl Details darüber, wie das Skript nach Administratorzugriff sucht, den Rahmen dieses Artikels sprengen würden, hier der Code, der für die Demonstration verwendet wird:
if( ([Security. Principal. WindowsPrincipal] [Security. Principal. WindowsIdentity]: : GetCurrent() ). IsInRole( [Security. Principal. WindowsBuiltInRole] "Administrator")){ Write-Output 'Wird als Administrator ausgeführt!'} Else{ Write-Output 'Running Limited!'} PauseSie werden feststellen, dass es jetzt zwei gibt"Pause" -Operationen in der Skript-Ausgabe - eine aus dem PowerShell-Skript und eine aus der Batch-Datei. Der Grund dafür wird im nächsten Schritt deutlicher.
Schritt 3: Administratorzugriff erhalten.
Wenn Ihr Skript keine Befehle ausführt, die eine Erhöhung erfordern, und Sie sich ziemlich sicher sind, dass Sie sich nicht darum kümmern müssen, dass die benutzerdefinierten Profile in die Quere kommen, können Sie den Rest überspringen. Wenn Sie jedoch Cmdlets auf Administratorebene ausführen, benötigen Sie dieses Stück.
Leider gibt es keine Möglichkeit, die Benutzerkontensteuerung für die Erhöhung innerhalb einer Batchdatei oder CMD-Sitzung zu aktivieren. PowerShell erlaubt uns dies jedoch mit Start-Prozess. Bei Verwendung von "-Verb RunAs" in seinen Argumenten versucht Start-Process, eine Anwendung mit Administratorberechtigungen zu starten. Wenn die PowerShell-Sitzung nicht bereits erhöht ist, wird eine UAC-Eingabeaufforderung ausgelöst. Um dies aus der Batch-Datei zum Starten unseres Skripts zu verwenden, werden am Ende zwei PowerShell-Prozesse generiert - einer zum Starten von Process und ein weiterer, der von Start-Process gestartet wird, um das Skript auszuführen. Die zweite Zeile der Batchdatei muss folgendermaßen geändert werden:
PowerShell.exe -Kommando "& Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass-Datei" "% ~ dpn0.ps1" "' -VerbRunAs} "Wenn die Stapeldatei ausgeführt wird, wird die erste Ausgabezeile vom PowerShell-Profilskript angezeigt. Dann wird eine UAC-Eingabeaufforderung angezeigt, wenn Start-Process versucht, MyScript.ps1 zu starten.
Nach dem Klicken auf die UAC-Eingabeaufforderung wird eine neue PowerShell-Instanz generiert. Da es sich um eine neue Instanz handelt, wird die Profilskriptanzeige natürlich erneut angezeigt. Dann läuft MyScript.ps1 und wir sehen, dass wir tatsächlich in einer erhöhten Sitzung sind.
Und es gibt den Grund, warum wir auch hier zwei Pausen haben. Wenn nicht im PowerShell-Skript, würden wir nie die Ausgabe des Skripts sehen - das PowerShell-Fenster würde einfach auftauchen und verschwinden, sobald das Skript fertig ist. Und ohne die Pause in der Batchdatei wären wir nicht in der Lage zu sehen, ob es überhaupt Fehler beim Start von PowerShell gegeben hat.
Schritt 4: Umgehen Sie benutzerdefinierte PowerShell-Profile.
Lassen Sie uns diese unangenehme benutzerdefinierte Profil Notiz jetzt loswerden, sollen wir? Hier ist es kaum störend, aber wenn das PowerShell-Profil eines Benutzers die Standardeinstellungen, Variablen oder Funktionen auf eine Weise ändert, die Sie mit Ihrem Skript nicht erwartet haben, können sie sehr problematisch sein. Es ist viel einfacher, das Skript ohne das Profil auszuführen, sodass Sie sich keine Sorgen machen müssen. Dazu müssen wir nur noch die zweite Zeile der Batch-Datei ändern:
PowerShell.exe -NoProfile -Command "&{ Start-Prozess PowerShell.exe -ArgumentList '-NoProfile-ExecutionPolicy Bypass-Datei" "% ~ dpn0.ps1 "" '-Verb RunAs} "Das Hinzufügen des Parameters" NoProfile "zu beiden PowerShell-Instanzen, die vom Skript gestartet werden, bedeutet, dass das Profilskript des Benutzers in beiden Schritten vollständig umgangen wird und unser PowerShell-Skript ausgeführt wirdeine ziemlich vorhersehbare Standardumgebung. Hier sehen Sie, dass in keiner der erzeugten Shells eine benutzerdefinierte Profilbenachrichtigung vorhanden ist.
Wenn Sie in Ihrem PowerShell-Skript keine Administratorrechte benötigen und Schritt 3 übersprungen haben, können Sie auf die zweite PowerShell-Instanz verzichten, und die zweite Zeile Ihrer Stapeldatei sollte wie folgt aussehen:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass-Befehl "& '% ~ dpn0.ps1'"Die Ausgabe sieht dann wie folgt aus:
( Natürlich können Sie bei Nicht-Administrator-Skripten in Ihrem PowerShell-Skript auf eine Skriptpause verzichtenauch an diesem Punkt, da alles im selben Konsolenfenster erfasst wird und trotzdem durch die Pause am Ende der Batch-Datei festgehalten wird.)
Abgeschlossene Batch-Dateien.
Abhängig davon, ob Sie Administratorberechtigungen für Ihr PowerShell-Skript benötigen( und Sie sollten sie wirklich nicht anfordern, wenn dies nicht der Fall ist), sollte die endgültige Stapeldatei wie eine der beiden unten aussehen.
Ohne Administratorzugriff:
@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass-Befehl "& '% ~ dpn0.ps1'" PAUSEMit Administratorzugriff:
@ECHO OFF PowerShell.exe -NoProfile -Command "&{Start-Process PowerShell.exe -ArgumentList '-NoProfile-ExecutionPolicy Bypass-Datei ""% ~ dpn0.ps1 ""' -Verb RunAs} "PAUSEDenken Sie daran, die Batchdatei in den gleichen Ordner wie das gewünschte PowerShell-Skript zu schreibenum es zu benutzen und ihm den gleichen Namen zu geben. Unabhängig davon, auf welchem System Sie diese Dateien verwenden, können Sie Ihr PowerShell-Skript ausführen, ohne sich mit den Sicherheitseinstellungen des Systems herumschlagen zu müssen. Sie können diese Änderungen natürlich jedes Mal manuell vornehmen, aber das erspart Ihnen diese Probleme und Sie müssen sich keine Gedanken darüber machen, die Änderungen später rückgängig zu machen.
Referenzen:
- Ausführen von PowerShell-Skripten aus einer Stapeldatei - Daniel Schroeders Programmierblog
- Prüfen auf Administratorberechtigungen in PowerShell - Hey, Scripting Guy! Blog