Ответ 1
Краткая версия
Как передать аргумент, содержащий кавычки, в собственную команду из PowerShell?
-
Используйте одиночные кавычки вместо двойных кавычек в строке аргумента:
"/p:Target='Data Source=(local)\SQL;Integrated Security=True'"
→/p:Target='Data Source=(local)\SQL;Integrated Security=True'
-
Использование обратной косой черты для двойных кавычек в строке аргумента & lowast;:
'/p:Target=\"Data Source=(local)\SQL;Integrated Security=True\"'
→/p:Target="Data Source=(local)\SQL;Integrated Security=True"
Если встроенные кавычки используются только для обработки аргумента как одной строки, а не как обязательная часть параметра, то можно использовать следующее:
-
Процитировать всю строку аргумента, а не вставлять кавычки в аргумент:
'/p:Target=Data Source=(local)\SQL;Integrated Security=True'
→/p:Target=Data Source=(local)\SQL;Integrated Security=True
-
Сбросьте все специальные символы PowerShell с backticks & lowast; (это можно сделать только как встроенный аргумент):
/p:Target=`"Data Source=`(local`)\SQL`;Integrated Security=True`"
или/p:Target=Data` Source=`(local`)\SQL`;Integrated` Security=True
→/p:Target=Data Source=(local)\SQL;Integrated Security=True
Полный пример командной строки (с использованием второй альтернативы):
PS> [string[]]$arguments = @(
'/target:Deploy',
'/p:UseSandboxSettings=False',
'/p:TargetDatabase=UpdatedTargetDatabase',
'/p:TargetConnectionString=\"Data Source=(local)\SQL;Integrate Security=True\"',
'C:\program files\MyProjectName.dbproj'
)
PS> ./echoargs $arguments
Arg 0 is </target:Deploy> Arg 1 is </p:UseSandboxSettings=False> Arg 2 is </p:TargetDatabase=UpdatedTargetDatabase> Arg 3 is </p:TargetConnectionString="Data Source=(local)\SQL;Integrate Security=True"> Arg 4 is <C:\program files\MyProjectName.dbproj>
Длинная версия
Вызов собственных команд - это нечто, что немного выросло, когда люди перемещаются между старой системой cmd и PowerShell (почти так же, как и "разделение параметров запятыми" ).
Я пробовал и суммировал все, что я знаю, по поводу вызова команды в PowerShell (v2 и v3) здесь, вместе со всеми примерами и ссылками, которые я могу собрать.
1) Прямой вызов собственных команд
1.1). В своем простейшем для исполняемого файла, находящегося в пути к среде, команда может быть вызвана непосредственно, так же, как вы назовете командлет PowerShell. p >
PS> Get-ItemProperty echoargs.exe -Name IsReadOnly
...
IsReadOnly : True
PS> attrib echoargs.exe
A R C:\Users\Emperor XLII\EchoArgs.exe
1.2) За пределами пути к среде, для команд в определенном каталоге (включая текущий), можно использовать полный или относительный путь к команде. Идея состоит в том, чтобы оператор явно объявлял "Я хочу вызвать этот файл", вместо того, чтобы позволить произвольному файлу, имеющему одно и то же имя, запускаться вместо него (см. Этот вопрос для получения дополнительной информации о безопасности PowerShell). Если не использовать путь, когда это необходимо, это приведет к ошибке "термин не распознан".
PS> echoargs arg
The term 'echoargs' is not recognized as the name of a cmdlet, function, script file,
or operable program...
PS> ./echoargs arg
Arg 0 is <arg>
PS> C:\Windows\system32\attrib.exe echoargs.exe
A R C:\Users\Emperor XLII\EchoArgs.exe
1.3) Если путь содержит специальные символы, можно использовать оператор вызова или escape-символ. Например, исполняемый файл, начинающийся с числа, или расположенный в каталоге, содержащем пробел.
PS> $env:Path
...;C:\tools\;...
PS> Copy-Item EchoArgs.exe C:\tools\5pecialCharacter.exe
PS> 5pecialCharacter.exe special character
Bad numeric constant: 5.
PS> & 5pecialCharacter.exe special character
Arg 0 is <special>
Arg 1 is <character>
PS> `5pecialCharacter.exe escaped` character
Arg 0 is <escaped character>
PS> C:\Users\Emperor XLII\EchoArgs.exe path with spaces
The term 'C:\Users\Emperor' is not recognized as the name of a cmdlet, function,
script file, or operable program...
PS> & 'C:\Users\Emperor XLII\EchoArgs.exe' path with spaces
Arg 0 is <path>
Arg 1 is <with>
Arg 2 is <spaces>
PS> C:\Users\Emperor` XLII\EchoArgs.exe escaped` path with` spaces
Arg 0 is <escaped path>
Arg 1 is <with spaces>
2) Вызов косвенных команд
2.1) Если вы не вводите команду в интерактивном режиме, а вместо этого сохраняете путь в переменной, оператор вызова также может использоваться для вызова команды с именем в переменной.
PS> $command = 'C:\Users\Emperor XLII\EchoArgs.exe'
PS> $command arg
Unexpected token 'arg' in expression or statement.
PS> & $command arg
Arg 0 is <arg>
2.2) Аргументы, переданные команде, также могут храниться в переменных. Аргументы в переменных могут передаваться по отдельности или в массиве. Для переменных, содержащих пробелы, PowerShell автоматически удалит пробелы, чтобы собственная команда рассматривала их как один аргумент. (Обратите внимание, что оператор вызова рассматривает первое значение как команду и остальные значения в качестве аргументов, аргументы не должны сочетаться с командной переменной.)
PS> $singleArg = 'single arg'
PS> $mushedCommand = "$command $singleArg"
PS> $mushedCommand
C:\Users\Emperor XLII\EchoArgs.exe single arg
PS> & $mushedCommand
The term 'C:\Users\Emperor XLII\EchoArgs.exe single arg' is not recognized as the
name of a cmdlet, function, script file, or operable program...
PS> & $command $singleArg
Arg 0 is <single arg>
PS> $multipleArgs = 'multiple','args'
PS> & $command $multipleArgs
Arg 0 is <multiple>
Arg 1 is <args>
2.3) Формат массива особенно полезен для создания динамического списка аргументов для собственной команды. Для каждого признака, который должен быть распознан как отдельный параметр, важно, чтобы аргументы сохранялись в массиве переменные, а не только сгруппированы в одну строку. (Обратите внимание, что общая аббревиатура $args
- это автоматическая переменная в PowerShell, которая может привести к перезаписыванию сохраненных в ней значений, вместо этого лучше использовать описательное имя, например $msbuildArgs
, чтобы избежать конфликта имен.)
PS> $mungedArguments = 'initial argument'
PS> $mungedArguments += 'second argument'
PS> $mungedArguments += $(if( $someVariable ) { 'dynamic A' } else { 'dynamic B' })
PS> ./echoargs $mungedArguments
Arg 0 is <initial argumentsecond argumentdynamic B>
PS> $arrayArguments = @('initial argument')
PS> $arrayArguments += 'second argument'
PS> $arrayArguments += $(if( $someVariable ) { 'dynamic A' } else { 'dynamic B' })
PS> ./echoargs $arrayArguments
Arg 0 is <initial argument>
Arg 1 is <second argument>
Arg 2 is <dynamic B>
2.4) Кроме того, для сценариев, функций, командлетов и т.д. PowerShell v2 может отправлять именованные аргументы, содержащиеся в хэш-таблице, используя метод "splatting", не беспокоясь о порядке параметров. Это не работает с собственными командами, которые не участвуют в объектной модели PowerShell и могут обрабатывать только строковые значения.
PS> $cmdletArgs = @{ Path = 'EchoArgs.exe'; Name = 'IsReadOnly' }
PS> $cmdlet = 'Get-ItemProperty'
PS> & $cmdlet $cmdletArgs # hashtable object passed to cmdlet
Cannot find path 'C:\Users\Emperor XLII\System.Collections.Hashtable'...
PS> & $cmdlet @cmdletArgs # hashtable values passed to cmdlet
...
IsReadOnly : True
PS> ./echoargs @cmdletArgs
Arg 0 is <Name>
Arg 1 is <IsReadOnly>
Arg 2 is <Path>
Arg 3 is <EchoArgs.exe>
3) Вызов собственных команд со сложными аргументами
3.1)Для простых аргументов, как правило, достаточно автоматического экранирования, используемого для собственных команд. Тем не менее, для круглых скобок, знаков доллара, пробелов и т.д., Символы , используемые PowerShell, должны быть экранированы, чтобы их можно было послать как собственные команды, не интерпретировав их синтаксическим анализатором. Это можно сделать с помощью escape-символа обратного хода, `
или путем помещения аргумента внутри строки с одной кавычкой.
PS> ./echoargs money=$10.00
Arg 0 is <money=.00>
PS> ./echoargs money=`$10.00
Arg 0 is <money=$10.00>
PS> ./echoargs value=(spaces and parenthesis)
The term 'spaces' is not recognized as the name of a cmdlet, function, script file,
or operable program...
PS> ./echoargs 'value=(spaces and parenthesis)'
Arg 0 is <value=(spaces and parenthesis)>
3.2) К сожалению, это не так просто, когда задействованы двойные кавычки. В рамках обработки аргументов для собственных команд процессор PowerShell пытается нормализовать все двойные кавычки в аргументе, чтобы содержимое аргумента sans кавычек передавалось как отдельное значение для собственной команды. Обработка собственных команд выполняется как отдельный шаг после синтаксического анализа, поэтому нормальное экранирование не будет работать для двойных кавычек; только экранированные одиночные кавычки или двойные кавычки с обратной косой чертой могут использоваться.
PS> ./echoargs value="double quotes"
Arg 0 is <value=double quotes>
PS> ./echoargs 'value="string double quotes"'
Arg 0 is <value=string>
Arg 1 is <double>
Arg 2 is <quotes>
PS> ./echoargs value=`"escaped double quotes`"
Arg 0 is <value=escaped double quotes>
PS> ./echoargs 'value=\"backslash escaped double quotes\"'
Arg 0 is <value="backslash escaped double quotes">
PS> ./echoargs value='single quotes'
Arg 0 is <value=single quotes>
PS> ./echoargs "value='string single quotes'"
Arg 0 is <value='string single quotes'>
PS> ./echoargs value=`'escaped` single` quotes`'
Arg 0 is <value='escaped single quotes'>
3.3) В PowerShell v3 добавлен новый символ стоп-анализа --%
(см. about_Parsing
). При использовании перед сложными аргументами --%
передаст аргументы как есть без разбора или расширения переменных, за исключением cmd-подобных %ENVIRONMENT_VARIABLE%
значений.
PS> ./echoargs User:"$env:UserName" "Hash"#555
Arg 0 is <User:Emperor XLII>
Arg 1 is <Hash>
PS> ./echoargs User: "$env:UserName" --% "Hash"#555
Arg 0 is <User:Emperor XLII>
Arg 1 is <Hash#555>
PS> ./echoargs --% User: "%USERNAME%" "Hash"#555
Arg 0 is <User:Emperor XLII>
Arg 1 is <Hash#555>
Это также можно использовать для удаления одной строки, представляющей несколько аргументов, путем передачи символа стоп-синтаксиса в строке & lowast; (хотя наилучшей практикой является не аргумент munge в первую очередь).
PS> $user = 'User:"%USERNAME%"'
PS> $hash = 'Hash#' + $hashNumber
PS> $mungedArguments = $user,$hash -join ' '
PS> ./echoargs $mungedArguments
Arg 0 is <User:%USERNAME% Hash#555>
PS> ./echoargs --% $mungedArguments
Arg 0 is <$mungedArguments>
PS> ./echoargs '--%' $mungedArguments
Arg 0 is <User:Emperor XLII>
Arg 1 is <Hash#555>
4) Отладка собственных команд
Существует два ключевых инструмента для отладки аргументов, которые PowerShell передает в собственные команды.
4.1) Первый EchoArgs.exe
, консольное приложение из Расширения сообщества PowerShell, который просто записывает аргументы, переданные ему между угловыми скобками (как показано в приведенных выше примерах).
4.2) Вторая Trace-Command
, командлет, который может показать много деталей о том, как PowerShell обрабатывает конвейер. В частности, источник трассировки NativeCommandParameterBinder
покажет, что PowerShell получает и передает на собственную команду.
PS> Trace-Command *NativeCommand* { ./echoargs value="double quotes" } -PSHost
DEBUG: NativeCommandParameterBinder : Raw argument string: "value=double quotes"
DEBUG: NativeCommandParameterBinder : Argument 0: value=double quotes
PS> Trace-Command *NativeCommand* { ./echoargs 'value="double quotes"' } -PSHost
DEBUG: NativeCommandParameterBinder : Raw argument string: "value="double quotes""
DEBUG: NativeCommandParameterBinder : Argument 0: value=double
DEBUG: NativeCommandParameterBinder : Argument 1: quotes
PS> Trace-Command *NativeCommand* { ./echoargs value=`"double quotes`" } -PSHost
DEBUG: NativeCommandParameterBinder : Raw argument string: value="double quotes"
DEBUG: NativeCommandParameterBinder : Argument 0: value=double quotes
PS> Trace-Command *NativeCommand* { ./echoargs 'value=\"double quotes\"' } -PSHost
DEBUG: NativeCommandParameterBinder : Raw argument string: "value=\"double quotes\""
DEBUG: NativeCommandParameterBinder : Argument 0: value="double quotes"
Другие ресурсы
Статьи
- 2012-01-02 - PowerShell V3 CTP2 обеспечивает лучший аргумент Переход к EXE
- 2011-03-10 - Проблема с вызовом устаревших/родных приложений из PowerShell
- 2010-11-04 - Escaping Spaces
- 2010-02-01 - Испытания и невзгоды использования MSDeploy с PowerShell
- 2008-10-17 - Выполнение команд, для которых требуются кавычки и переменные, практически невозможно [Connect]
- 2006-05-15 - Невозможно ввести аргумент, содержащий двойные кавычки [Connect]
Вопросы
- 2013-09-11 - powershell выполняет внешнюю команду, не принимающую параметр
- 2013-02-20 - Параметры с двойными кавычками неправильно переданы в Scriptblock по ArgumentList
- 2013-01-02 - ОШИБКА: Описание = Неверный запрос
- 2012-09-18 - Как выполнить внешнюю программу с параметрами в PowerShell?
- 2012-09-10 - Вызвать исполняемый файл (w/parameters) из powershell script
- 2012-08-16 - Как передать значение свойства, содержащее точку с запятой в командной строке MSBuild при ее запуске из PowerShell?
- 2012-08-08 - Вызовите ruby script из powershell
- 2012-08-01 - Кронштейны или кавычки, нарушающие команду powershell
- 2012-07-13 - Проблемы с использованием powershell для обеспечения безопасного доступа по метке
- 2012-06-13 - Отсутствует аргумент -m, используя svn в windows powershell
- 2012-06-01 - Аргумент командной строки Powershell с пробелами и фигурными скобками?
- 2012-04-18 - Разнесенные пути, msbuild и psake
- 2012-04-12 - Сделать оболочку Power игнорировать точку с запятой
- 2012-03-08 - Простая версия Msbuild Powershell с параметром не работает
- 2012-02-10 - Цитата Madness в Powershell
- 2012-01-18 - Powershell: запустите msiexec с динамически создаваемыми параметрами
- 2012-01-18 - Синтаксис и двойные кавычки оператора PowerShell
- 2012-01-16 - PowerShell - передача рассчитанных путей с пробелами
- 2012-01-09 - powershell: script, чтобы запустить программу с параметрами?
- 2011-12-20 - Powershell - вызов icacls с скобками, включенными в параметры
- 2011-12-15 - Журнал Msbuild не работает, когда выполняется через powershell
- 2011-12-06 - Передайте параметры InstallUtil из Powershell
- 2011-11-23 - Выполнение exe с аргументами с использованием Powershell
- 2011-11-08 - Powershell удаляет кавычки при запуске
- 2011-09-16 - Команды, выполняемые в PowerShell с переменными, окруженными кавычками, терпят неудачу. Почему?
- 2011-07-25 - Синтаксический разбор Powershell странным образом (включая краткий анализ синтаксического анализа цитат в один из ответов)
- 2011-07-15 - powershell сбрасывает двойные кавычки из аргументов командной строки
- 2011-06-14 - В Powershell, как вы произвольно выполняете собственную команду из строки?
- 2011-06-03 - Powershell вызовет msbuild с вложенными кавычками
- 2011-05-13 - powershell - передача параметров в exe
- 2011-03-02 - Почему этот PowerShell script не смог выполнить эту внешнюю команду правильно?
- 2011-01-09 - Выполнение EXE файла с помощью powershell script
- 2010-12-13 - Аргументы командной строки для exe
- 2010-10-08 - Что происходит с этой командной строкой PowerShell, цитируя/экранируя?
- 2010-10-05 - Запуск exe с использованием powershell из каталога с пробелами в нем
- 2010-08-28 - Выполнение команды, хранящейся в переменной из Powershell
- 2010-08-17 - Как вы вызываете msdeploy из powershell, когда параметры имеют пробелы?
- 2010-04-12 - Как подавить кавычки в командах Powershell для исполняемых файлов
- 2010-01-26 - powershell отправляет несколько параметров во внешнюю команду
- 2009-11-04 - Как запустить exe в powershell с параметрами с пробелами и кавычками
- 2009-03-16 - PowerShell - Переключатели Start-Process и Cmdline
- 2009-01-14 - Как избежать аргументов командной строки в Powershell?