Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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:empmsi"" (it does work like expected with cmd.exe).

Why do powershell and cmd.exe behaviour different, and how can it be fixed?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
774 views
Welcome To Ask or Share your Answers For Others

1 Answer

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:

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

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

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 from cmd.exe / a batch file (including expansion of environment-variable references such as %OS%).

... --% PUBLICPROPERTY=""

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" becomes
    PUBLICPROPERTY=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 just PUBLICPROPERTY=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 into PUBLICPROPERTY=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 into PUBLICPROPERTY=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'


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...