Friday, October 23, 2009

Mind Your Trailing Backslashes

When you are testing in the Visual C# IDE, and your test setup includes command line arguments that contain backshlashes, take caution.

The Problem

Take a fairly typical (for me) command argument string such as the following.

"C:\Documents and Settings\David\My Documents\_CLIENTS\EMCERT\"

Enter that into the Command Line Arguments text box on the Debug tab of the Project Properties page of a Console program project, put a breakpoint anywhere in its Main() function (in Program.cs). Press F5, make the Locals window visible, and display the first element of the Args array.

  [0] "C:\\Documents and Settings\\David\\My Documents\\Visual Studio 2005\\Projects\\wwBldNbrMgr\\wwBldNbrMgr\"" string

Do you see the extra quote at the end?

Now, press Shift-F5 to stop the the debugger, and change the Command Line Arguments string as shown below.

"C:\Documents and Settings\David\My Documents\Visual Studio 2005\Projects\wwBldNbrMgr\wwBldNbrMgr\ "

Not the space that I inserted between the backslash and the quote at the end of the string.

Repeat the debug session, and display the argument.

  [0] "C:\\Documents and Settings\\David\\My Documents\\Visual Studio 2005\\Projects\\wwBldNbrMgr\\wwBldNbrMgr\\ " string

I'll bet that is the string you expected to see the first time.

The Explanation

If you've never written and debugged console mode programs in C, using a tool such as Microsoft Visual C++, you might be scratching your head. So was I, for an embarrassingly long time.

After several hours of beating my head against the wall, I realized why the debugger was behaving in this seemingly bizarre way. Under the hood, the Microsoft .NET runtime must be using the scanf() function, or a derivative of it, to read the command line. Like its cousins, printf(), fprintf(), sprintf(), and others on the output side of the standard C library, scanf() interprets escape sequences, such as \", \r, \n, \t, and a host of others, in addition to the infamous printf() format strings.

The Solution

Once I understood what was happening under the hood, the solution is straightforward.

  1. If the last character in your Command Line Arguments string is a backslash, enter two of them.
  2. If the last two characters in your Command Line Arguments string are a backslash followed by a quotation mark, put a space between them.
  3. If you realize that your Command Line Arguments string contains an escape sequence, such as \", \r, \n, \t, take appropriate action to prevent it from being interpreted as an escape sequence. Usually, all that's needed is to double the backslash, so that \t becomes \t, for example.
  4. If the string you see in the debugger is missing a character or two that you entered into Command Line Arguments, check that part of the string for an escape sequence. Pay close attention to lower case characters that immediately follow a backslash, because all escape sequences involve lower case letters and numbers.

Escape sequences are covered in the help topics for the C# programming language in MSDN library, because you can use them in regular string literals. This topic closes with a handful of references, the first of which is to the definition of a regular string literal, as that term applies to the C# programming language.

References