Repository navigation
double quotes in string literal arguments get removed when calling native commands #3049
Copy link
Copy link
Closed
Labels
Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aOS-LinuxOS-macOSResolution-DuplicateThe issue is a duplicate.The issue is a duplicate.WG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtime
Description
Steps to reproduce
On macOS run
osascript -e 'display notification "FOO" with title "TITLE"'
Expected behavior
Show notification, just like in bash
Actual behavior
PS /> osascript -e 'display notification "FOO" with title "TITLE"'
21:24: execution error: The variable FOO is not defined. (-2753)
PS /> bash
bash-3.2$ osascript -e 'display notification "FOO" with title "TITLE"'
bash-3.2$
Environment data
> $PSVersionTable
Name Value
---- -----
PSVersion 6.0.0-alpha
PSEdition Core
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 3.0.0.0
GitCommitId v6.0.0-alpha.14
CLRVersion
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1 Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aOS-LinuxOS-macOSResolution-DuplicateThe issue is a duplicate.The issue is a duplicate.WG-Enginecore PowerShell engine, interpreter, and runtimecore PowerShell engine, interpreter, and runtime
Activity
thezim commentedon Jan 27, 2017
The following change does work.
Per the man page.
vors commentedon Jan 27, 2017
Greg Zimmerman (@thezim) good to know, thank you!
I still think there is an issue, because it's super unintitive for me, why I need to escape these quotes, when the whole parameter is already wrapped in the single-quoted string.
Also it related to the pillar of "making PS more compatible with existing shells to allow more commands work thru copy-paste".
thezim commentedon Jan 27, 2017
vor I agree. I would prefer your example to work too.
thezim commentedon Jan 28, 2017
Invoke-AppleScript would be a nice cmdlet for macOS. Following would lead me to believe is could be done.
http://jonathanpeppers.com/Blog/xamarin-ios-under-the-hood-calling-objective-c-from-csharp
https://docs.microsoft.com/en-us/dotnet/articles/standard/native-interop
thezim commentedon Jan 28, 2017
sergei (@vors) This works too.
[-]apple script doesn't play nicely with powershell[/-][+]double quotes in string literal arguments get removed when calling native commands[/+]lzybkr commentedon Jan 28, 2017
Repro (using test code in our repo):
lzybkr commentedon Jan 28, 2017
Note that the behavior is consistent with Windows, but maybe it shouldn't be.
DemiMarie commentedon Feb 3, 2017
Why is it this way on Windows? If I recall correctly, this behavior was a major annoyance.
TSlivede commentedon Feb 8, 2017
Correct me if I'm wrong, but isn't this a duplicate of #1995 ?
Jason Shirk (@lzybkr) I think it absolutely must be consistent with Windows, but double escaping should not be necessary on any platform.
BrucePay commentedon Feb 17, 2017
sergei (@vors) Note that in the workaround on macOS, the double quotes are being escaped with ''. PowerShell doesn't treat \ as the escape character so clearly osascript is doing it's own escape processing.
Jason Shirk (@lzybkr) the value of argv[0] is exactly what I'd expect it to be. Since windows CreateProcess passes arguments as a simple string, process startup code needs to break that string up into individual arguments. It does this by processing the quotes that are passed, doing quote removal for string arguments.
lzybkr commentedon Feb 17, 2017
Bruce Payette (@BrucePay) - The annoyance is that calling a process differs from calling a command:
Add to this - the behavior of bash differs from windows - it is more like calling a script/function than an executable.
I don't see a perfect solution. As I see it, the incompatible goals are:
People do find the behavior on Windows confusing.
People do find many command lines for cmd/bash and should just work in PowerShell - this is one example where it doesn't.
PowerShell Core could chose to break compatibility with Windows PowerShell to deliver on goals 1, 2, and 3.
We could make no changes, and we've delivered on 3 and 4.
TSlivede commentedon Feb 17, 2017
Bruce Payette (@BrucePay) Although Windows does only send a single Commandline to the new Process, almost every CLI-App splits this Commandline according to these rules. Therefore Powershell should build the Commandline in a way, that matches those rules instead of just sometimes adding quotes around arguments.
Almost every other modern Commandshell on windows does this:
linebuf::fromargv)list2cmdline)BuildCommandLine, Comment: "N backslashes followed a quote -> insert N * 2 + 1 backslashes then a quote.")People also expect this from Powershell. See:
Jason Shirk (@lzybkr) I think
4.is not really a Problem, as it never really worked on Windows and even changed from time to time. For example in Powershell on Windows 10 (PSVersion: 5.1.14393.693; PSEdition: Desktop; BuildVersion: 10.0.14393.693) it's completely impossible to senda"b cto theargv[1]of the next Process via a normal call:echoargs 'a\"b c'-> Commandline:\path\to\echoargs.exe a\"b cechoargs '"a\"b c"'-> Commandline:\path\to\echoargs.exe ""a\"b c""Necessary Commandline for
argv[1]=a"b c:\path\to\echoargs.exe "a\"b c"The only option to accomplish this is via
--%, but that gets really botched, if one needs to pass content from calculations or variables.lzybkr commentedon Feb 17, 2017
TSlivede - I feel comfortable saying somebody depends on the current behavior.
That said, compatibility can't really be guaranteed (different runtimes amongst other big differences), so it's really a best effort.
Personally I'm in favor of the breaking change - far too many people avoid the easy way of running an external command because of issues like this.
TSlivede commentedon May 14, 2017
sergei (@vors) asked in #1995 if anybody wants to start an RFC process.
I wrote a draft, here it is.
SteveL-MSFT commentedon May 24, 2017
Dupe of #1995
jeff-hykin commentedon May 9, 2021
For anyone looking for an essentially bulletproof workaround to the original issue, here's one:
Example Usage
Code
This should always escape the arguments correctly, even when taking into account the planned 7.2 change here.
Comparison