Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does C# appear to partially un-escape command line arguments?

I am trying to pass multiple paths as arguments to a console application but am getting an "Illegal characters in path" error. It appears that something is mistaking the last two characters of the argument "C:\test\" for an escaped double-quote.

For example, if I create a new empty console application in C# like so:

static void Main(string[] args)
{
    Console.WriteLine(args[0]);
    Console.ReadLine();
}

and, under Project Properties -> Debug I add a command line argument like so:

Project properties showing CLI Argument: "C:\test\"

then my output looks like this:

Command prompt showing output: C:\test"

If the value is being evaluated/un-escaped, why does \t not become a tab?

If the value is NOT being evaluated/un-escaped, why does \" become a double-quote?

(Note: I know I can work around this by, for example, trimming trailing backslashes etc. I'm asking for help understanding why the arguments appear to be partially evaluated)

like image 921
Alex McMillan Avatar asked Apr 12 '17 02:04

Alex McMillan


1 Answers

Admittedly this relates to Microsoft C Command Line Arguments, but I have tested that these rules are also followed for C#. Command line arguments are separated into the string args[] array prior to being passed in to the application.

Parsing C Command-Line Arguments

  • Arguments are delimited by white space, which is either a space or a tab.

  • A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. Note that the caret (^) is not recognized as an escape character or delimiter.

  • A double quotation mark preceded by a backslash, \", is interpreted as a literal double quotation mark (").

  • Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

  • If an even number of backslashes is followed by a double quotation mark, then one backslash () is placed in the argv array for every pair of backslashes (\), and the double quotation mark (") is interpreted as a string delimiter.

  • If an odd number of backslashes is followed by a double quotation mark, then one backslash () is placed in the argv array for every pair of backslashes (\) and the double quotation mark is interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

These rules seem to agree with the results you are seeing.

I ran the following console application to test these rules:

static void Main(string[] args)
{
    foreach (string s in args)
    {
        Console.WriteLine(s);
    }
    Console.ReadLine();
}

With the following command line arguments:

arg1 "arg2 arg3" arg4\" "arg5\"" arg6\\\"

Output:

arg1
arg2 arg3
arg4"
arg5"
arg6\"

The reason your input argument appears unescaped is that the first double-quotation is interpreted to be the starting string delimiter, and the second double-quotation is escaped by the preceding backslash and interpreted as a literal double-quotation - not an ending delimiter.

like image 67
khargoosh Avatar answered Sep 18 '22 23:09

khargoosh