Setting Public Property Values on the Command Line of an msi follows the pattern
MyInstaller.msi PUBLICPROPERTY="someValue"
This works on "Command Prompt" aka cmd.exe and powershell.
But
MyInstaller.msi PUBLICPROPERTY=""
does not work like expected in powershell. I expected that it sets PUBLICPROPERTY to null but it sets PUBLICPROPERTY to the value "CURRENTDIRECTORY="C:\temp\msi\"" (it does work like expected with cmd.exe).
Why do powershell and cmd.exe behaviour different, and how can it be fixed?
PowerShell, on Windows of necessity, performs re-quoting of your arguments behind the scenes.
This invisible re-quoting doesn't always work as expected, such as in this case.
You can solve the problem by tweaking your quoting:
Note that using
'...'
won't work if you want to include the values of PowerShell variables / expressions in the argument.Additionally, in PSv3+ you can use
--%
, the stop-parsing symbol, to make PowerShell pass the remaining arguments through as-is, as if you had called fromcmd.exe
/ a batch file (including expansion of environment-variable references such as%OS%
).Again, you won't be able to reference PowerShell variables or expressions in the arguments that way.
As for what happens without the techniques above:
PUBLICPROPERTY="someValue"
becomesPUBLICPROPERTY=someValue
PUBLICPROPERTY="some Value"
, due to whitespace, becomes"PUBLICPROPERTY=some Value"
, i.e., the entire argument is enclosed in"..."
.PowerShell-internally an argument such as
PUBLICPROPERTY="someValue"
has its quotes stripped: if you pass such an argument to a PowerShell cmdlet or function, it will see justPUBLICPROPERTY=someValue
.On passing such a value on to an external program, PowerShell decides situationally whether double-quoting is needed, but that quoting is then only ever applied to the entire argument - the initial placement of the
"
chars. is lost.Thus,
PUBLICPROPERTY="someValue"
turns intoPUBLICPROPERTY=someValue
and is passed on as-is, because it contains no embedded whitespace, so PowerShell applies no double-quoting.By contrast,
PUBLICPROPERTY="some Value"
turns intoPUBLICPROPERTY=some Value
, which is passed on as"PUBLICPROPERTY=some Value"
, because the presence of whitespace requires double-quoting in order to preserve the value as a single argument.Note that PowerShell only ever applies double-quoting to arguments passed to external programs, because that is the only style of quoting that can be assumed to be understood by all programs.
The re-quoting logic has changed over time and has bugs, which, regrettably, are here to stay due to backward compatibility concerns.
E.g,
'3 " of rain'
becomes"3 " of rain"
, which is broken, because the embedded"
lacks escaping; the workaround is to anticipate that and explicitly do what PowerShell should be doing automatically: escape the embedded"
as\"
for the benefit of the external program:'3 \" of rain'