Обработка команд Powershell (передача в переменных)
Я создаю Powershell script для развертывания некоторого кода, а часть процесса - вызов инструмента сжатия командной строки RAR.EXE для резервного копирования некоторых папок.
Я пытаюсь динамически строить параметры, а затем команду powershell вызывать команду с переменными, но у меня возникают проблемы. Он не работает...
Запустите следующий script, и вы должны увидеть, о чем я говорю. Параметры, передаваемые как переменная, искажаются. Если я передаю всю команду + параметры, я получаю печально известное сообщение "не распознано как командлет...".
Спасибо за любую помощь!
echo "this should succeed"
& cmd /c echo foo
echo "why does this echo out an additional double quote?"
$param = "/c echo foo"
& cmd "$param"
echo "this does the same"
$param = "/c echo foo"
& cmd $param
echo "escaping the slash doesn't work either..."
$param = "`/c echo foo"
& cmd $param
echo "this fails, but why?"
$cmd = "cmd /c echo foo"
&$cmd
Ответы
Ответ 1
Оператор вызова '&' В этом случае нет необходимости. Он используется для вызова команды в новой области. Обычно это используется для вызова команды, указанной строкой или скриптомблоком. Он также имеет преимущество, которое любые переменные, созданные в PowerShell script, отбрасываются после завершения команды, и область действия исчезает.
Однако, поскольку cmd является EXE, он выполняется в совершенно другом процессе. FWIW, вы получаете аналогичную выходную информацию непосредственно из cmd.exe:
> cmd "/c echo foo"
foo"
Таким образом, дополнительная цитата в конце - это проблема cmd.exe. Как правило, вам нужно оставить команду отдельно от параметров, когда PowerShell выполняет синтаксический разбор, чтобы вызвать команду, например.
45> & { $foo = "foo" }
46> $foo # Note that $foo wasn't found - it went away with the scope
47> . { $foo = "foo" } # dotting executes in the current scope
48> $foo
foo
Значимым исключением здесь является то, что Invoke-Expression ведет себя как функция "оценить эту строку". Используйте с осторожностью, особенно если пользователь предоставляет строку. Ваш день может сосать, если они предоставят "ri C:\-r".
В этом случае, как предложили другие, я вытащил /c из строки $param string и задал ее, например:
cmd /c $param
Или используйте Invoke-Expression, но используйте с осторожностью. BTW, когда вы пытаетесь отладить проблемы с отправкой аргументов в EXE из PowerShell, проверьте утилиту echoargs в расширениях сообщества PowerShell (http://pscx.codeplex.com). Это очень удобно:
49> $param = "/c echo foo"
50> echoargs $param
Arg 0 is </c echo foo>
Это показывает, что cmd.exe получает "/c echo foo" в качестве единственного аргумента. "/c" должен быть отдельным аргументом из "echo foo" (команда для выполнения).
Ответ 2
Другим способом, который я нашел, было создание массива аргументов для командной строки и использование этого с оператором apersand и call. Что-то вроде этого:
$exe = "cmd";
[Array]$params = "/c", "echo", "foo";
& $exe $params;
Это сработало для меня.
Я изначально нашел эту технику здесь:
http://techstumbler.blogspot.com/2009/12/windows-commands-with-arguments-in.html
Ответ 3
У меня были проблемы с оператором call и в прошлом при попытке вызвать команды исполняемого типа, как вы пытаетесь. Не уверен, что я понимаю, почему. Invoke-Expression, однако, всегда работает в этом контексте:
PS C:\> $cmd = "cmd /c echo foo"
PS C:\> Invoke-expression $cmd
foo
Ответ 4
Ваш последний пример, если не удается, потому что "&" обрабатывает строку как один аргумент, поэтому она ищет программу с именем "cmd/c echo foo.exe".:)
Это работает:
& $cmd $params
Что касается проблемы с двойной кавычкой, похоже, что cmd не нравится кавычки вокруг аргументов, которые PowerShell ставит. Он получает следующее:
cmd "/c echo foo"
Итак, я думаю, что он обрабатывает все после /c как точную команду, так вот так:
echo foo"
Некоторые программы командной строки и фанк синтаксический разбор командной строки (вот почему PowerShell использует это задание для функций и командлетов). В случае cmd я бы предложил следующее:
$param = "echo foo"
& cmd /c $param
Ответ 5
Это артефакт использования cmd/c, я думаю. работает
$param = "echo foo"
cmd /c $param
работает отлично. Если у вас нет примера с реальным кодом, немного сложно выполнить съемку.
Ответ 6
Args обрабатываются по-разному, если они содержатся в String:
PS D:\> echo "1 2 3"
1 2 3
PS D:\> echo 1 2 3
1
2
3
Те же результаты возникают, когда вы используете переменную args:
PS D:\> $param = "1 2 3"
PS D:\> echo $param
1 2 3
РЕШЕНИЕ состоит в использовании массива:
PS D:\> $param = @(1,2,3)
PS D:\> echo $param
1
2
3