Недавно у меня возникли проблемы с использованием GnuWin32 из PowerShell, когда задействованы двойные кавычки.
При дальнейших исследованиях, похоже, PowerShell лишает двойные кавычки из аргументов командной строки, даже если они правильно экранированы.
PS C:\Documents and Settings\Nick> echo '"hello"'
"hello"
PS C:\Documents and Settings\Nick> echo.exe '"hello"'
hello
PS C:\Documents and Settings\Nick> echo.exe '\"hello\"'
"hello"
Обратите внимание, что двойные кавычки передаются в командлет PowerShell echo, но при передаче в качестве аргумента echo.exe двойные кавычки удаляются без экранирования обратная косая черта (даже несмотря на то, что escape-символ PowerShell - это обратная сторона, а не обратная косая черта).
Это кажется ошибкой для меня. Если я передаю правильные экранированные строки в PowerShell, тогда PowerShell должен позаботиться о том, какое бы экранирование не потребовалось, но он вызывает команду.
Что здесь происходит?
В настоящее время исправление заключается в выводе аргументов командной строки в соответствии с этими правилами (которые, по-видимому, используются при вызове API CreateProcess
, который PowerShell использует для вызова файлов .exe):
- Чтобы передать двойную кавычку, выполните обратную косую черту:
\"
→"
- Чтобы передать одну или несколько обратных косых черт, за которыми следует двойная кавычка, сбрасывайте каждую обратную косую черту с помощью другой обратной косой черты и избегайте цитаты:
\\\\\"
→\\"
- Если не следовать двойной кавычки, для обратных косых черт не требуется экранирование:
\\
→\\
Обратите внимание, что для избежания двойных кавычек в экранированной строке Windows API в PowerShell может потребоваться дополнительное экранирование двойных кавычек.
Вот несколько примеров: echo.exe из GnuWin32:
PS C:\Documents and Settings\Nick> echo.exe "\`""
"
PS C:\Documents and Settings\Nick> echo.exe "\\\\\`""
\\"
PS C:\Documents and Settings\Nick> echo.exe "\\"
\\
Я предполагаю, что это может быстро стать адом, если вам нужно передать сложный параметр командной строки. Конечно, ничто из этого не зарегистрировано в документации CreateProcess()
или PowerShell.
Также обратите внимание, что это необязательно для передачи аргументов с двойными кавычками для .NET-функций или командлетов PowerShell. Для этого вам нужно только избежать двойных кавычек в PowerShell.