The blog and home page of Simon Soanes
Skip to content
[ Log On ]

Attempting to pass paths with a space or any other command line argument that requires being enclosed in quotes was causing me some mild frustration, it looks like the .NET implementation that fills args is incorrectly mangling the data that is passed into it.  A major bug that shouldn't have gotten through QA exists somewhere...

If you pass a path into a program that is foreach-ing over the args collection through the debug properties in visual studio (and presumably through anywhere else!) you go from:-

program.exe /path "c:\my documents\" /dostuff 1

Turn into two rather than four arguments:-

args[0] is /path
args[1] is c:\my documents" /dostuff 1

Which is downright strange, as you'd expect to get:-

args[0] is /path
args[1] is c:\my documents\
args[2] is /dostuff
args[3] is 1

What on earth are they doing to cause such a mess to command line arguments... Anyway, whilst I'm not sure when this started but thankfully the Environment.CommandLine is left intact and undamaged, so you can do something like this to fix the problem:-

private static string[] FixedExtractCmdLineElements()
            List<string> elements = new List<string>();

            string[] firstParts = Environment.CommandLine.Split(' ');

            //reparse it
            StringBuilder temporaryPart = new StringBuilder("");
            bool inside = false;
            foreach (string part in firstParts)
                //are we inside a quoted part, or did we just find a quote?
                if (!inside && !part.Contains("\""))
                    if (inside)
                        //we are still inside a quote...
                        temporaryPart.Append(" " + part);

                        if (part.Contains("\""))
                            //then we are also at the end!
                            elements.Add(temporaryPart.Replace("\"", "").ToString()); //add the part minus its quotes to the array
                            //all done!
                            inside = false;
                        //else we just found a quote!
                        inside = true;
                        temporaryPart = new StringBuilder(part);

            return elements.ToArray();
Permalink  2 Comments 

Used by chris at 05/13/2010 16:32:39
Howdy, Just had to use this badboy - I thought it was the Visual Studio build events that were messing up until I remembered you mentioning this puppy before.

Thanks! I would have honestly speant anouther hour chasing my tail around this one had I not remembered.

note by chris at 05/13/2010 16:39:26
A quick note about it though - comparing a run of using args[] against args = FixedExtractCmdLineElements();

args passed into the main() method contains the first parameter as args[0] whereas your method places the filename of the running app into args[0] and the first argument into args[1] ala batch file programming.

While I find your method more agreeable (hey, I'm always for MORE information) it's a point to note that you cant just drop the function over the top of the args parameter without winding all of your indexes forward one.