Как подавить кавычки в командах PowerShell для исполняемых файлов

Есть ли способ подавить кавычки вокруг каждого аргумента командной строки, которые PowerShell любит генерировать, а затем передавать внешним исполняемым файлам для аргументов командной строки, в которых есть пробелы?

Вот ситуация:

Один из способов распаковать множество инсталляторов - это команда вида:

msiexec /a <packagename> /qn TARGETDIR="<path to folder with spaces>"

Попытка выполнить это из PowerShell оказалась довольно сложной. PowerShell любит заключать параметры с пробелами в двойные кавычки. Следующие строки:

msiexec /a somepackage.msi /qn 'TARGETDIR="c:\some path"'

msiexec /a somepackage.msi /qn $('TARGETDIR="c:\some path"')

$td = '"c:\some path"'

msiexec /a somepackage.msi /qn TARGETDIR=$td

Все результаты в следующей командной строке (как сообщается Win32 GetCommandLine() API):

"msiexec" /a somepackage.msi /qn "TARGETDIR="c:\some path""

Эта командная строка:

msiexec /a somepackage.msi TARGETDIR="c:\some path" /qn

результаты в

"msiexec" /a fooinstaller.msi "TARGETDIR=c:\some path" /qn

Кажется, что PowerShell любит заключать результаты выражений, предназначенных для представления одного аргумента в кавычках, при передаче их во внешние исполняемые файлы. Это прекрасно работает для большинства исполняемых файлов. Тем не менее, MsiExec очень специфичен в отношении правил цитирования, которые он хочет, и не будет принимать ни одну из командных строк, сгенерированных PowerShell для путей, в которых есть пробелы.

Есть ли способ подавить это поведение?

6 ответов

Избегайте внутренних кавычек, как это:

msiexec /a somepackage.msi TARGETDIR=`"c:\some path`" /qn

Вот функция, которую я использую для лучшей обработки нескольких аргументов и аргументов с пробелами и кавычками. Обратите внимание, что в приведенных ниже блоках кода не закрашивайте там, где строки начинаются и заканчиваются правильно, и вы должны использовать `, чтобы экранировать кавычки, которые вы хотите в параметре.

function InstallMSIClient{
$Arguments = @()
$Arguments += "/i"
$Arguments += "`"$InstallerFolder\$InstallerVerFolder\Install.msi`""
$Arguments += "RebootYesNo=`"No`""
$Arguments += "REBOOT=`"Suppress`""
$Arguments += "ALLUSERS=`"1`""
$Arguments += "/passive"

Write-Host "Installing $InstallerVerFolder."
Start-Process "msiexec.exe" -ArgumentList $Arguments -Wait }

В моем блоге есть более полный пример. [ http://www.christowles.com%5D

Поместите весь аргумент в кавычки и избегайте внутренних кавычек. В противном случае PowerShell попытается разобрать его:

msiexec /a <packagename> /qn 'TARGETDIR=\"<path to folder with spaces>\"'

Я только что столкнулся с проблемой. Следующее работало для меня:

&cmd /c "msiexec /i `"$appName.msi`" /l* `"$appName.msi.log`" /quiet TARGETDIR=`"D:\Program Files (x86)\$appName\`""

Ключ выполнял cmd, а не msiexec напрямую. Это имело два преимущества:

  1. Я мог бы обернуть всю команду msiexec в строку, чтобы она разрешала переменную $appName, все еще используя обратную галочку для экранирования кавычек вокруг TARGETDIR.
  2. Мне удалось использовать $LastExitCode для проверки успеха / неудачи операции msiexec. По какой-то причине $LastExitCode не устанавливается при непосредственном вызове msiexec (hat-tip: http://web.archive.org/web/20100907072034/http://www.powergui.org/thread.jspa?threadID=13022)

У меня нет ответа, но этот парень, кажется, на что-то.
http://www.eggheadcafe.com/software/aspnet/33777311/problem-escaping-command.aspx

Я не мог заставить это работать для меня.

Вот еще кто-то, кто сообщил о проблеме тоже: _http://powershell.com/cs/forums/p/2809/3751.aspx

Вот еще одна идея от кого-то: _http://www.roelvanlisdonk.nl/? P =1135

Это тоже не сработало для меня...

У меня нет ответа, но этот парень, кажется, на что-то. http://www.eggheadcafe.com/software/aspnet/33777311/problem-escaping-command.aspx

Да, похоже, они нашли решение в конце:

Наконец-то выяснили, как это сделать, используя выражение invoke

$installprop = "TARGETDIR=" + "```"" + $installpath + "```""

invoke-expression "msiexec /i $packagepath $installprop"

Я бы порекомендовал использовать здесь-строку, чтобы избежать необходимости выполнять все экранирование.

$command = @'
msiexec /a <packagename> /qn TARGETDIR="<path to folder with spaces>"
'@

invoke-expression $command
Другие вопросы по тегам