It’s more complicated than that though!
I was having related problem (writing front-end .exe that will call the back-end with all parameters passed + some extra ones) and so i looked how people do that, ran into your question. Initially all seemed good doing it as you suggest arg.Replace (@"\", @"\\").Replace(quote, @"\"+quote)
.
However when i call with arguments c:\temp a\\b
, this gets passed as c:\temp
and a\\b
, which leads to the back-end being called with "c:\\temp" "a\\\\b"
– which is incorrect, because there that will be two arguments c:\\temp
and a\\\\b
– not what we wanted! We have been overzealous in escapes (windows is not unix!).
And so i read in detail http://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs.aspx and it actually describes there how those cases are handled: backslashes are treated as escape only in front of double quote.
There is a twist to it in how multiple \
are handled there, the explanation can leave one dizzy for a while. I’ll try to re-phrase said unescape rule here: say we have a substring of N \
, followed by "
. When unescaping, we replace that substring with int(N/2) \
and iff N was odd, we add "
at the end.
The encoding for such decoding would go like that: for an argument, find each substring of 0-or-more \
followed by "
and replace it by twice-as-many \
, followed by \"
. Which we can do like so:
s = Regex.Replace(arg, @"(\\*)" + "\"", @"$1$1\" + "\"");
That’s all…
PS. … not. Wait, wait – there is more! 🙂
We did the encoding correctly but there is a twist because you are enclosing all parameters in double-quotes (in case there are spaces in some of them). There is a boundary issue – in case a parameter ends on \
, adding "
after it will break the meaning of closing quote. Example c:\one\ two
parsed to c:\one\
and two
then will be re-assembled to "c:\one\" "two"
that will me (mis)understood as one argument c:\one" two
(I tried that, i am not making it up). So what we need in addition is to check if argument ends on \
and if so, double the number of backslashes at the end, like so:
s = "\"" + Regex.Replace(s, @"(\\+)$", @"$1$1") + "\"";