有没有办法抑制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为路径生成的任何命令行。
有没有办法抑制这种行为?
答案 0 :(得分:8)
像这样逃避内部引号:
msiexec /a somepackage.msi TARGETDIR=`"c:\some path`" /qn
答案 1 :(得分:7)
这是一个我用来更好地处理多个参数的函数以及带空格和引号的函数。请注意,对于下面的代码块,请不要在字符串的开始和结束位置正确显示颜色,并且必须使用`来转义参数中所需的引号。
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]
答案 2 :(得分:0)
将整个参数放在引号中并转义内部引号。否则PowerShell会尝试解析它:
msiexec /a <packagename> /qn 'TARGETDIR=\"<path to folder with spaces>\"'
答案 3 :(得分:0)
我没有答案,但这个家伙似乎正在做点什么 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
这对我来说也不起作用......
答案 4 :(得分:0)
我没有答案,但是这个家伙似乎正在做点什么。 http://www.eggheadcafe.com/software/aspnet/33777311/problem-escaping-command.aspx
是的,看起来他们最终找到了解决方案:
最后使用invoke-expression确定了如何执行此操作:
$installprop = "TARGETDIR=" + "```"" + $installpath + "```""
invoke-expression "msiexec /i $packagepath $installprop"
我建议使用here-string,以避免必须进行所有转义。
$command = @'
msiexec /a <packagename> /qn TARGETDIR="<path to folder with spaces>"
'@
invoke-expression $command
答案 5 :(得分:0)
我刚刚遇到问题。以下对我有用:
&cmd /c "msiexec /i `"$appName.msi`" /l* `"$appName.msi.log`" /quiet TARGETDIR=`"D:\Program Files (x86)\$appName\`""
密钥是直接执行cmd而不是msiexec。这有两个好处: