Powershell Удаление аргумента кавычек

Я использую Start-Process для запуска другого экземпляра Powershell от имени администратора, но когда я пытаюсь передать список аргументов в виде переменной или простой строки, Powershell удаляет кавычки. Ниже приведена команда, которую я использую:

$argu = '-noexit "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat"';
powershell Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

Это ошибка, которую я получаю:

x86 : The term 'x86' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:88
+ ... Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\v ...
+                    ~~~
    + CategoryInfo          : ObjectNotFound: (x86:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Спасибо заранее за любую помощь.

Обновлять:

$argu = '''-noexit ""C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat""''';
powershell Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

Это почти исправляет ситуацию, но теперь я получаю сообщение об ошибке выше во втором окне вместо первого.


person dkneeland    schedule 30.07.2018    source источник
comment
ты пробовал $argu = '-noexit ""C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat""'   -  person No Refunds No Returns    schedule 30.07.2018
comment
$argu = "-noexit", "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" Тоже должен это сделать.   -  person Paxz    schedule 30.07.2018
comment
@NoRefundsNoReturns Обновлено   -  person dkneeland    schedule 30.07.2018


Ответы (1)


(A) Из изнутри PowerShell:

$argu = '-noexit -command & \"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat\"'
Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

Примечание: я не звоню Start-Process через powershell.exe, так как в этом обычно нет необходимости.

  • Встроенные " экранируются \, что требуется PowerShell, когда вы вызываете его CLI (возможно, это удивительно, учитывая, что внутри PowerShell именно ` действует как escape-символ).

    • That said given that the " are embedded inside '...' here, they shouldn't require extra escaping - see below.
  • Путь к файлу для выполнения имеет префикс оператора вызова &, поскольку он необходим для выполнения файлов, указанных в кавычках.

  • Обратите внимание, что я добавил -Command, что не является строго обязательным в Windows PowerShell, но было бы, если бы вы запускали свою команду из PowerShell Core (которое теперь по умолчанию равно -File).


В качестве альтернативы вы также можете указать свои аргументы по отдельности, как часть массива, что, возможно, является более чистым решением:

$argu = '-noexit', '-command', '&', 'de', 
  '\"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat\"'
Start-Process -Verb RunAs -FilePath powershell -ArgumentList $argu

К сожалению, даже в этом случае вам понадобятся дополнительные встроенные кавычки для аргументов, содержащих пробелы, что является известная Start-Process проблема отслеживается на GitHub.

Обработка PowerShell кавычек при вызове внешних программ обычно проблематична; текущие проблемы обобщены в этой проблеме GitHub.


(B) Из вне PowerShell (cmd.exe, пользовательское контекстное меню Проводника):

powershell -command Start-Process -Verb RunAs -FilePath powershell -ArgumentList '-noexit -command . ''C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat'''
  • Теперь используются одинарные-кавычки (с вложенными одинарными кавычками, экранированными как ''), потому что двойные кавычки существенно усложнили бы экранирование.

  • . используется вместо & для выполнения файла .bat, что позволяет избежать проблем с анализом &; хотя . обычно служит другой цели, чем &, два оператора ведут себя одинаково при вызове внешних программ.

  • Если вы также хотите установить рабочий каталог для сеанса PowerShell, который в конечном итоге открывается с повышенными правами, вам необходимо включить явный вызов Set-Location (cd) в командную строку, поскольку Start-Process -Verb RunAs по умолчанию всегда указывает на папку SYSTEM32 ( даже параметр -WorkingDirectory в этом случае не помогает).

    • Однако, чтобы это работало безопасно, вы должны заключить путь к каталогу, используя двойные-кавычки, учитывая, что имена файлов могут содержать одинарные кавычки; с %V в качестве пути к каталогу (который File Explorer предоставляет командам, вызываемым через настраиваемые контекстные меню), правильно экранированный вызов Set-Location выглядит следующим образом (хотел бы я пошутить):

      • Set-Location \"\"\"%V%\"\"\"

Интегрировано в полную команду (для краткости используется встроенный псевдоним Set-Location cd):

powershell -command Start-Process -Verb RunAs -FilePath powershell -ArgumentList '-noexit -command cd \"\"\"%V%\"\"\"; . ''C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat'''

Кроме того, PowerShell Core теперь имеет параметр командной строки -WorkingDirectory (-wd), который позволяет более надежно управлять каталогом запуска (pwsh -wd "c:\path\to\dir" ...); на самом деле именно вариант использования пользовательского контекстного меню File Explorer побудил ввести этот параметр .

person mklement0    schedule 30.07.2018