Open Aldaviva opened 3 months ago
This seems to also have affected RetrospectClientNotifier, and I fixed it with string replacement before parsing.
This seems like a CoreCLR runtime VM defect and not a BCL defect because the issue is present in the char** argv
argument passed from the VM to Environment.InitializeCommandLineArgs(char*,int,char**)
:
new string(argv[15]) // G:\Toca Race Driver 3"
// note the erroneous trailing quotation mark
Could the CLR be adamantly doing the right but dumb thing with the quotation mark escaping, and PowerShell is emitting pretty but illegal strings during directory tab completion?
The same problem also reproduces with a minimal C++ program that just reads the char* argv[]
value passed into main
, so this problem is not in the .NET VM or BCL. I think Microsoft shot themselves in the foot with their stupid Windows argument escaping rules, and PowerShell is technically doing the wrong thing according to those dumb rules.
I guess preprocessing the array in process is best. An extension method that takes the place of McMaster.Extensions.CommandLineUtils.CommandLineApplication.Parse
works well and is fairly portable.
When running a program, you may pass the path to a directory in an argument. On Windows, PowerShell tab-completes and quotes directories. For example, if you type
and then press Tab, PowerShell will complete this to
When you press Enter, PowerShell will start a program with the executable and arguments
So far, PowerShell and Windows are not doing anything incorrect. The command line arguments passed to
MyProgram.exe
will be correct as viewed in Task Manager, Process Explorer, Process Monitor. If the program to launch is a .NET program written in C#,Environment.GetCommandLineArgs()
and thestring[]
parameter toMain
will contain the last itemC:\Program Files"
, with an extra trailing quotation mark, which is incorrect. If you try to open or check if this directory exists, it fails, because the directory name is misspelled. The original trailing quotation mark was closing the opening one, which is now correctly gone. However, the trailing one was incorrectly interpreted as an escaped quotation mark because PowerShell preceded it with\
as a directory separator, in case you wanted to type more path segments easily without typing\
yourself. This is also trivially easy to do in Command Prompt as well, although PowerShell is more likely to do so because of its tab completion behavior. .NET then finds it has an unmatched quotation mark pair and terminates the string anyway, leaving the trailing quotation mark in the string.I think in the past I have worked around this issue with regular expressions, but I would like a more generalized and bulletproof solution, because this keeps happening and creating more duplicate, unnecessary work for me in each program I write.