Command Line Confusion
I kept getting wierd errors in a simple console application which takes a regular expression as an argument. The regular expression kept failing with an "Illegal \ at end of pattern" error. The odd thing was that I was properly escaping the \ as \\.
After some testing, I think I've convinced myself that this had nothing to do with regular expressions; there's something wacky about the way the .NET Framework handles commandline arguments which end in \\". Here's a simplified argument test application:
using System;
public class Test
{
public static void Main(string[] args)
{
Console.WriteLine("Environment.CommandLine: " + Environment.CommandLine);
for(int i=0;i<args.Length;i++)
{
OutputArg(i,args[i]);
Console.WriteLine();
}
}
static void OutputArg(int i,string arg)
{
Console.WriteLine("Environment.GetCommandLineArgs()[{0}]: {1}", i+1, Environment.GetCommandLineArgs()[i+1]);
Console.WriteLine("args[{0}]: {1}",i,arg);
//foreach(char c in arg) Console.WriteLine(c);
}
}
First, let's test it to see how it handles quoted and unqoted strings:
C:\Temp>CommandLineArgumentsTest.exe "monkey" potato
Environment.CommandLine: CommandLineArgumentsTest.exe "monkey" potato
Environment.GetCommandLineArgs()[1]: monkey
args[0]: monkey
Environment.GetCommandLineArgs()[2]: potato
args[1]: potato
Everything sees pretty good there - we've passed a quoted string and an unquoted string, and both work just fine.
Now, let's try it with some strings that end with two back slashes (\\):
C:\Temp>CommandLineArgumentsTest.exe "\\test\\" "\\test\\\"
Environment.CommandLine: CommandLineArgumentsTest.exe "\\test\\" "\\test\\\"
Environment.GetCommandLineArgs()[1]: \\test\
args[0]: \\test\
Environment.GetCommandLineArgs()[2]: \\test\"
args[1]: \\test\"
See what I'm talking about? The last \ vanishes like X-Files was all up in this place. Normally when things get strange, I turn to my good friend Reflector for some insight, but mscorlib.System.Environment.GetCommandLineArgsNative() is rather un-surprisingly native code and is thus well sheltered from Reflector's prying eyes.
After a bit of thought it looks like the second backslash is being "used up" by escaping the final quote. Let's try it with an unquoted argument:
C:\Documents and Settings\Jon\My Documents\My Code Snippets>CommandLineArgumentsTest.exe \\test\\
Environment.CommandLine: CommandLineArgumentsTest.exe \\test\\
Environment.GetCommandLineArgs()[1]: \\test\\
args[0]: \\test\\
Sure enough, everything's great there. That doesn't solve the problem, though - if there's a space in the string, it needs to be quoted so it's handled as one argument (e.g.
C:\Temp>CommandLineArgumentsTest.exe "\\test\\\\"
Environment.CommandLine: CommandLineArgumentsTest.exe "\\test\\\\"
Environment.GetCommandLineArgs()[1]: \\test\\
args[0]: \\test\\
It's still kind of odd to me, though - why doesn't it display that quote in \\test\\\", since it's been escaped? If the GetComandLineArg() is seeing the last two characters as \", wouldn't it make more sense for args[0] to be \\test\" rather than \\test\ ? As I understand it, escaping in both C# and RegEx is supposed to be handled in a left to right fashion, but this seems to be working right to left.