2017-05-10 2 views
3

Beim Versuch, eine Batch-Datei neu zu schreiben, habe ich in die Möglichkeit der Verwendung von Powershell untersucht. Das Hauptproblem, das ich damit hatte, war, dass .ps1 Dateien nicht standardmäßig ausführbar sind. Ich fand eine Lösung here, die ich weiter unten kopieren würde, aber ich bin sehr verwirrt über die Syntax in der ersten Zeile:Seltsame Umleitung in Batch/Powershell Polyglot

<# : batch script 
@echo off 
setlocal 
cd %~dp0 
powershell -executionpolicy remotesigned -Command "Invoke-Expression $([System.IO.File]::ReadAllText('%~f0'))" 
endlocal 
goto:eof 
#> 
# here write your powershell commands... 

Hier ist, was ich von der Prüfung wissen:

  • Der Raum zwischen <# und : ist erforderlich, obwohl es mehrere sein kann.
  • Es kann auch eine Nummer 0-9 im Voraus haben, wie 3<# :, was mich vermuten lässt, dass es einige Seltsamkeit mit Redirects und Labels gibt.
  • Der Text nach dem Doppelpunkt ignoriert und notwendig, nicht
  • Wenn ich einen Befehl, bevor es, wie git <# : batch script hinzufügen, zeigt die Shell, dass es versuchte, git : batch script 0<# zu bewerten und die Datei
  • die angegebenen nicht finden kann, ändern # zu einem gültigen Dateinamen macht die Beschwerde weg (natürlich)
  • Der Versuch, die Zeile in einer interaktiven Sitzung ausführen, tatsächlich beschweren sich darüber, nicht in der Lage, die angegebene Datei zu finden, aber von einem Skript ausführen (auch wenn es ist die einzige Zeile in der Datei .cmd) führt im Hintergrund zu

Die letzte Kugel ist der Teil, den ich versuche herauszufinden. Was ist anders an den Umgebungen? Mein Verständnis war, dass ein Teil des Problems war, dass das Ausführen einer Bat-Datei so analysiert wird, als ob jede Zeile manuell eingegeben würde. Warum beklagt es sich nicht, dass # eine ungültige Datei ist, wenn es über ein Skript aufgerufen wird?

+0

Sind Sie sicher, dass es sich nicht um einen mehrzeiligen Kommentar handelt, der zum Anzeigen des "alten" Batchdateicodes verwendet wird? – Moerwald

Antwort

3

"... das Ausführen einer Bat-Datei wird analysiert, als ob jede Zeile manuell eingegeben würde."

Nein, Parser-Regeln unterscheiden sich manchmal zwischen Befehlszeile und Batch-Datei und in diesem Fall ist der Unterschied kritisch.

Es beschwert sich über # eine ungültige Datei in der Befehlszeile zu sein und nicht in Batch-Datei, weil das <# : Konstrukt (zum Chargen Parser) ist nur ein Label umgeleitet. Die gleiche Art von Label, die Sie in goto :label oder call :label verwenden.

Das bedeutet, dass die Umleitung, die nicht in der Batchdatei als "Befehl" der Umleitung ausgeführt wird, eine Beschriftung ist, wird in der Befehlszeile ausgeführt, da Sie keine Beschriftung in einer Befehlszeile haben können.

+0

Gibt es Unterlagen, die das zeigen? Ich bin immer noch nicht ganz sicher, warum der Unterschied besteht, da es scheint, dass ich Etiketten in der interaktiven Sitzung erstellen kann? –

+0

@MattSoucy, Wenn Sie etwas wie ': label' von der Kommandozeile aus verwenden, haben Sie kein Label (Sie können nicht' goto' oder 'call'), sondern einen * null Befehl * (Ich muss es geben ein Name), soweit das erste nicht leere/nicht-Trennzeichen ein Doppelpunkt ist. Sie können ': label

+0

In Ordnung, danke. Kannst du das in die Antwort selbst einbauen? Ich werde es als akzeptiert markieren. –

1

Der Trick ist, dass Sie ein gültiges Konstrukt für beide, Powershell und Batch benötigen.
Für Powershell ist nur der <# wichtig, um einen mehrzeiligen Kommentar zu öffnen.

Für die Stapelverarbeitung benötigen Sie einen gültigen Code, der jedoch trotz des Status echo on nicht sichtbar ist.
Daher ist ein Doppelpunkt in dieser Situation perfekt, da Beschriftungslinien nicht angezeigt werden, auch nicht mit echo on.

Sie können das Ergebnis des Parsers sehen, wenn Sie den Doppelpunkt durch REM ersetzen.

<# REM Batch script 

Ausgang:

c:\Temp>REM batch script 0<# 

Die # ist ein gültiger Dateiname, aber die Datei selbst wird nie accesed.