首页 > 解决方案 > 在命令行上设置公共属性值

问题描述

在 msi的命令行上设置公共属性值遵循模式

MyInstaller.msi PUBLICPROPERTY="someValue"

这适用于“命令提示符”又名 cmd.exe 和 powershell。

MyInstaller.msi PUBLICPROPERTY=""

在 powershell 中不像预期的那样工作。我预计它将 PUBLICPROPERTY 设置为 null,但它将 PUBLICPROPERTY 设置为值“CURRENTDIRECTORY="C:\temp\msi\""(它确实像预期的 cmd.exe 一样工作)。

为什么 powershell 和 cmd.exe 行为不同,如何解决?

标签: powershellwixwindows-installerparameter-passingquoting

解决方案


在 Windows 上,PowerShell 会在幕后重新引用您的论点。

这种不可见的重新引用并不总是按预期工作,例如在这种情况下。

您可以通过调整引用来解决问题:

... PUBLICPROPERTY=`"`"  # `-escape the " chars.

... 'PUBLICPROPERTY=""'  # use enclosing '...', so " chars. can be used as-is

请注意,'...'如果您想在参数中包含 PowerShell 变量/表达式的值,则 using 将不起作用。

此外,在 PSv3+ 中,您可以使用--%停止解析符号来使 PowerShell按原样传递剩余的参数,就好像您从cmd.exe/ 批处理文件调用一样(包括扩展环境变量引用,例如%OS%)。

... --% PUBLICPROPERTY=""

同样,您将无法以这种方式在参数中引用 PowerShell 变量或表达式。


至于没有上述技术会发生什么:

  • PUBLICPROPERTY="someValue"变成
    PUBLICPROPERTY=someValue

  • PUBLICPROPERTY="some Value",由于空格,变为
    "PUBLICPROPERTY=some Value",即整个参数包含在 中"..."

PowerShell-在内部一个参数,例如去掉PUBLICPROPERTY="someValue"引号:如果你将这样一个参数传递给 PowerShell cmdlet 或函数,它只会看到.PUBLICPROPERTY=someValue

在将这样的值传递给外部程序时,PowerShell会根据情况决定是否需要双引号,但这种引号只会应用于整个参数"-字符的初始位置。丢失了。

因此,PUBLICPROPERTY="someValue"变成并按原样PUBLICPROPERTY=someValue传递,因为它不包含嵌入式空格,因此 PowerShell 不应用双引号。

相比之下,PUBLICPROPERTY="some Value"变成PUBLICPROPERTY=some Value,它作为 传递"PUBLICPROPERTY=some Value",因为空格的存在需要双引号才能将值保留为单个参数。

请注意,PowerShell 只对传递给外部程序的参数应用引号,因为这是唯一可以假定所有程序都可以理解的引用样式。

重新引用的逻辑随着时间的推移发生了变化,并且存在错误,遗憾的是,由于向后兼容性问题,这些错误仍然存​​在。

比如 become '3 " of rain'"3 " of rain"它被破坏了,因为嵌入"缺少转义;解决方法是预见到这一点并明确执行 PowerShell 应该自动执行的操作:为了外部程序的利益"转义嵌入式:\"'3 \" of rain'


推荐阅读