Ulfs Blog

14.5.2019, 18:30

Batch ruft Powershell

Ulfs Blog

In der c't 8/2019 gibt es einen Artikel (Seite 168f), der aufzeigt, wie man ein Powershellskript als Batchskript startet. Hintergrund ist, dass Batchskripte durch Doppelklick ausgeführt werden, während Powershellskripte nur über das Kontextmenü ausgeführt werden – und es dabei auch noch Probleme geben kann.

Die Lösung der c't liest als Batchskript die Skriptdatei ein und schreibt den Powershell-Teil als PS1-Datei auf die Festplatte, um diese Datei dann als Powershellskript auszuführen. Anschließend wird die Datei wieder gelöscht. Wegen diesem Umweg über die Festplatte behagt mir der Ansatz nicht.

Ein Artikel auf How-To Geek beschreibt eine andere Lösung, bei der es zwei Skriptdateien gibt: das Batchskript, welches dann das Powershellskript ausführt. Auch wenn der Ansatz den Vorteil hat, dass die Powershell-Befehle in einer PS1-Datei liegen und damit von den üblichen Codeeditoren erkannt werden, so dass die Syntax korrekt hervorgehoben wird, bleibt der Nachteil mit den zwei Dateien.

Leider kann Powershell Skriptdateien nur ausführen, wenn sie die Endung PS1 haben. Die Endung BAT oder CMD wie für Batchdateien ist nicht möglich. Mein Ansatz ist daher, den Inhalt des Skriptes zu lesen und als solchen auszuführen. Wie man prinzipiell Powershellskripte aus einem String ausführt, steht in einem Beitrag von Tome Tanasovski.

Die Idee ist, dass die Batchdatei einen Powershell-Befehl ausführt, der dieselbe Datei als Text einliest, den Batch-Teil weglässt und den Rest dynamisch ausführt. Dies wird mit dem folgenden Einzeiler (Zeilenumbrüche nur wegen der Lesbarkeit) erreicht:

@start powershell -NoProfile -ExecutionPolicy Bypass -Command "
	$content = [IO.File]::ReadAllText('%~f0');
	if ($content -match '(?smi)[^\n]*\n(.*)') {
		& $ExecutionContext.InvokeCommand.NewScriptBlock($matches[1])
	}
" & exit /b
	
# Powershellcode...
Write-Host "Powershell"