简体   繁体   中英

command line arguments given to a C# program are parsed wrong

I wrote a little program, that has the following command line for example:

prog.exe -p -z "E:\temp.zip" -v "f:\" -r -o -s –c
prog.exe -p -z "E:\temp.zip" -v f:\ -r -o -s –c
prog.exe -p -z "E:\temp.zip" -v "f:\log" -r -o -s –c

This command line is being generated by another program that inserts the quotation marks around the file and path names automatically to prevent spaces being recognized as argument separators.

The first command line is then being parsed by the .Net framework as:

args     {string[5]}        string[]
[0]        "-p"      string
[1]        "-z"      string
[2]        "f:\\temp.zip"   string
[3]        "-v"      string
[4]        "f:\" -r -o -s -c" string

But it should be ( the result from the second command line):

args      {string[9]}          string[]
[0]        "-p"                string
[1]        "-z"                string
[2]        "f:\\temp.zip"      string
[3]        "-v"                string
[4]        "f:\\"              string
[5]        "-r"                string
[6]        "-o"                string
[7]        "-s"                string
[8]        "-c"                string

A possible solution would be to check the file and path names in the calling application if they contain spaces and only then append the quotation marks around the names.

But is there another solution?

I created a little batch file that would display the command line parameters. With your first command line, I get

1 -p
2 -z
3 "E:\temp.zip"
4 -v
5 "f:\"
6 -r
7 -o
8 -s
9 –c

as it should. If .NET parses it differently, that would be a major bug. Just to check, I created a test console app. The results were:

0  -p
1  -z
2  E:\temp.zip
3  -v
4  f:" -r -o -s -c

I didn't think that was possible! So I researched a little and I got to this link: Everyone quotes command line arguments the wrong way which explains why the command line parser is essentially flawed. (I know it's for C++, but it applies) which led me to the rules of parsing for command line parameters which says \\" is interpreted as an escaped quote, as opposed to how the operating system sees it (which is gross).

Conclusion: if you want to fix the command line, you need to escape the slash before a quote so instead of "f:\\" you need "f:\\\\" . The other solution is to use Environment.CommandLine which gets you the entire command line, executable included, and you can parse it yourself. More on this here: Getting raw (unsplit) command line in .NET .

Just for completeness' sake, I'll throw this in: Split string containing command-line parameters into string[] in C# , which discusses how to split a command line string into parameters using system functions.

After some more research, I realized that there are several standards of command line argument parsing, depending on compiler and operating system and its version, and that the only way to be consistent is to parse the raw command line yourself.

For example, using CommandLineToArgvW on Environment.CommandLine replicated exactly a call to Environment.GetCommandLineArgs() which returns the exact same thing as the args array given to the Main method.

I found a very detailed page about this problem: http://daviddeley.com/autohotkey/parameters/parameters.htm which I believe is the definitive answer to the general question of command line parsing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM