Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
819 views
in Technique[技术] by (71.8m points)

powershell - Setting Public Property Values on the Command Line

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

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

1 Reply

0 votes
by (71.8m points)

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'


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...