Gerade für Pfadangaben sind „Gänsefüßchen“ unverzichtbar, damit Whitespace als Teil des Pfades interpretiert wird. Klassiker: C:\Program Files
Manchmal soll der Pfad aber gar nicht sofort von PowerShell verwertet, sondern zusammen mit den Anführungszeichen irgendwohin geschrieben werden, um sie dann später von einem anderen Prozess wieder einzulesen. So möchte man zum Beispiel eine geplante Augabe in Windows mit PowerShell anlegen und den kompletten Befehl mit allen Argumenten samt Dateipfaden darin speichern. Doch wie macht man das?
Wie es nicht geht
Offensichtlich kann man es nicht so schreiben:
$action = "PowerShell.exe -File "D:\My Scripts\Download-Files.ps1""
Output:
Unexpected token 'D:\My' in expression or statement.
Was ist passiert? Das erste Paar von Anführungszeichen kennzeichnet PowerShell.exe -File
als String, und die Zeichen danach werden erfolglos als Befehl interpretiert.
Die folgende Variante produziert zwar keinen Fehler, ist aber trotzdem falsch, weil die Anführungszeichen um den Pfad in der Ausgabe fehlen:
$file_path = "D:\My Scripts\Download-Files.ps1"
$action = "PowerShell.exe -File $file_path"
$action
Output:
PowerShell.exe -File D:\My Scripts\Download-Files.ps1
So ausgeführt würde der Befehl fehlschlagen.
Die zweitbeste Lösung
Erfolg verspricht auf den ersten Blick, den Pfad in doppelten Anführungszeichen zu belassen, aber dafür den String in einfache Anführungszeichen zu fassen:
$action = 'PowerShell.exe -File "D:\My Scripts\Download-Files.ps1"'
$action
Output:
PowerShell.exe -File "D:\My Scripts\Download-Files.ps1"
Es funktioniert auch umgekehrt:
$action = "PowerShell.exe -File 'D:\My Scripts\Download-Files.ps1'"
$action
Output:
PowerShell.exe -File 'D:\My Scripts\Download-Files.ps1'
Man macht sich dabei zunutze, dass Zeichen zwischen gleichartigen Anführungszeichen als Strings interpretiert werden.
Was wäre, wenn der Befehl Variablen benötigte?
$folder = "folder_a"
$timeout = 3600
$action_1 = 'PowerShell.exe -File "D:\My Scripts\$folder\Download-Files.ps1" -Timeout $timeout'
$action_1
$action_2 = "PowerShell.exe -File 'D:\My Scripts\$folder\Download-Files.ps1' -Timeout $timeout"
$action_2
Output:
PowerShell.exe -File "D:\My Scripts\$folder\Download-Files.ps1" -Timeout $timeout
PowerShell.exe -File 'D:\My Scripts\folder_a\Download-Files.ps1' -Timeout 3600
Bei $action_1
wurden wegen der einfachen Anführungszeichen keine Variablen aufgelöst. Wenn der String wie bei $action_2
von doppelten Anführungszeichen eingerahmt wird, löst PowerShell die Variablen jedoch auf – ist das also unsere Lösung?
Nun, wahrscheinlich in den meisten Fällen. In unserem Beispiel ist der Befehl hingegen für eine Aktion einer geplanten Aufgabe bestimmt – und dort wird CMD-Syntax erwartet. Das bedeutet: Einfache Anführungszeichen sind nicht erlaubt. Der Dateipfad im Skript muss von doppelten Anführungszeichen umrahmt sein, aber das geht ja nicht, wenn schon der String doppelte Anführungszeichen nutzt …
Jetzt haben wir schon so viel Zeit investiert und immer noch keine Lösung!
Sicher mit Maske auch in PowerShell
Glücklicherweise wird alles ganz einfach, wenn man weiß, was Maskierungszeichen oder escape characters sind. Kurz gesagt erfüllen die Anführungszeichen eine bestimmte Funktion für die Programmiersprache, aber wenn man ihnen das Maskierungszeichen voranstellt, verlieren sie diese Funktion und werden stattdessen als Text interpretiert. In PowerShell ist das Maskierungszeichen das Gravis-Akzentzeichen `
und führt zum gewünschten Ergebnis, wenn man die Anführungszeichen des Dateipfads damit schmückt:
$folder = "folder_a"
$timeout = 3600
$action = "PowerShell.exe -File `"D:\My Scripts\$folder\Download-Files.ps1`" -Timeout $timeout"
$action
Output:
PowerShell.exe -File "D:\My Scripts\folder_a\Download-Files.ps1" -Timeout 3600
Die doppelten Anführungszeichen bleiben erhalten, und die Variablen werden korrekt eingesetzt. So kann der Befehl zum Beispiel in der CMD oder in einer geplanten Aufgabe eingesetzt werden.