Command line arguments, paths with spaces, parsing

2020-05-07 15:23发布

问题:

I have an issue that's nearly identical to the one outlined here (Console app not parsing correctly args with white spaces) but that answer has no bearing on my situation.

I'm receiving arguments to my simple program that are paths and path+filenames with potentially lots of spaces in them. What's happening is that spaces in the paths are generating many more arguments than I actually have. I was manually reconstructing what I needed by passing through the args array, but I discovered today that if the filename has two spaces my method won't work, and I can't know that in the program to fix it.

Upload "\somesrv\Data\cust\99999_Test4\Working\" "\somesrv\Data\cust\99999_Test4\Working\99999_Test4-GUAST - Buyers List PA 11 15 14_112514_101753 AM_Sht=And stuff_Automation\99999_Test4-GUAST - Buyers List PA 11 15 14_112514_101753 AM_Sht=And stuff_Automation.zip"

So in the case of that set of arguments I get an args[] with 21 elements. Given that there's a pair of spaces at one point I have no hope of correcting this.

Is there anything I can do to make sure that the paths come through in tact? On the giving or receiving end is fine, as I'm in control of both, but not the paths/filenames themselves.

Code:

static void Main(string[] args)
{
    //args 0 = Switch value
    //args 1 = Working Directory
    //args 2 = Mail.dat zip file

    if (args.Length == 0)
    {
        Environment.Exit(-1);
    }

    string maildatName = args[1].Substring(args[1].IndexOf("Working")+8, args[1].Length - (args[1].IndexOf("Working")+8)) + " ";

    for (int x = 2; x < args.Length; x++)
    {
        maildatName += args[x];
        maildatName += " ";
    }

    args[1] = args[1].Substring(0, args[1].IndexOf("Working") + 7);
    maildatName = maildatName.Trim();
}

回答1:

It is caused by the \" at the end of your first argument.

If you remove the trailing slash or add an extra slash before the quote then you will get two arguments. The quote is being escaped and is considered part of the first argument until it hits the next quote 2 characters later. After that you are no longer inside of a quote and thus each space results in another argument added to the args array.

This is caused by the fact that .Net uses CommandLineToArgvW to process command line arguments and the rules it uses to handle escaping of characters.

Jon Galloway has a writeup on this

To quote:

CommandLineToArgvW has a special interpretation of backslash characters when they are followed by a quotation mark character ("), as follows:

  • 2n backslashes followed by a quotation mark produce n backslashes followed by a quotation mark.
  • (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark.
  • n backslashes not followed by a quotation mark simply produce n backslashes.


回答2:

It is because youre slash here Working\", when you add another slash it works correctly I believe so make It <snip>...Working\\"

edit: I just tested it myself, with a double \\ you get 3 items :)

Also see http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx



回答3:

Try this, Join the args into a string again, then Split that string on the double quote character.

string parms = String.Join(" ", args);
string[] arguments = parms.Split('\"');
...

BTW: This is a work around for the problem John Koerner has explained.