Как подавить кавычки в командах 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 для путей, в которых есть пробелы.

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

Ответ 1

Сбросьте внутренние кавычки следующим образом:

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

Ответ 2

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

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]

Ответ 3

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

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

Ответ 4

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

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

Здесь кто-то еще сообщает об этой проблеме: _http://powershell.com/cs/forums/p/2809/3751.aspx

Вот другая идея кем-то: _http://www.roelvanlisdonk.nl/р = 1135

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

Ответ 5

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

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

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

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

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

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

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

invoke-expression $command

Ответ 6

Немного старого вопроса, но я просто попал в проблему.

Следующие работали для меня:

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

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

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