22

I'm trying to pass command-line arguments to a C# application, but I have problem passing something like this

"C:\Documents and Settings\All Users\Start Menu\Programs\App name" 

even if I add " " to the argument.

Here is my code:

 public ObjectModel(String[] args) { if (args.Length == 0) return; //no command line arg. //System.Windows.Forms.MessageBox.Show(args.Length.ToString()); //System.Windows.Forms.MessageBox.Show(args[0]); //System.Windows.Forms.MessageBox.Show(args[1]); //System.Windows.Forms.MessageBox.Show(args[2]); //System.Windows.Forms.MessageBox.Show(args[3]); if (args.Length == 3) { try { RemoveInstalledFolder(args[0]); RemoveUserAccount(args[1]); RemoveShortCutFolder(args[2]); RemoveRegistryEntry(); } catch (Exception e) { } } } 

And here is what I'm passing:

C:\WINDOWS\Uninstaller.exe "C:\Program Files\Application name\" "username" "C:\Documents and Settings\All Users\Start Menu\Programs\application name" 

The problem is I can get the first and the second args correctly, but the last one it gets as C:\Documents.

Any help?

4
  • 1
    What are you trying to start this from? Command line or another program? If the latter - what is the language? Commented Mar 17, 2009 at 9:48
  • What happens when you pass an argument like this into your application? Commented Mar 17, 2009 at 9:48
  • Can you past your code that tries to access the argument and also the full command line you are typing, such as c:\myapp.exe "c:\documents\appname" Commented Mar 17, 2009 at 9:49
  • Looks okay, what exactly goes wrong? Commented Mar 17, 2009 at 10:03

6 Answers 6

29

I just ran a check and verified the problem. It surprised me, but it is the last \ in the first argument.

"C:\Program Files\Application name\" <== remove the last '\' 

This needs more explanation, does anybody have an idea? I'm inclined to call it a bug.


Part 2, I ran a few more tests and

"X:\\aa aa\\" "X:\\aa aa\" next 

becomes

X:\\aa aa\ X:\\aa aa" next 

A little Google action gives some insight from a blog by Jon Galloway, the basic rules are:

  • the backslash is the escape character
  • always escape quotes
  • only escape backslashes when they precede a quote.
Sign up to request clarification or add additional context in comments.

5 Comments

It's fixed by removing \ from the first arg. Thanks alot
If you want that trailing backslash, you can add another one. That is, "abd\\" on the command line results in an argument of "abd\".
@Henk: Sorry. Forest/trees here. I need a vacation.
Here is a GitHub project with Encode/Decode methods that handle issues mentioned by Jon Galloway: github.com/ericpopivker/Command-Line-Encoder
5

To add Ian Kemp's answer

If you assembly is called "myProg.exe" and you pass in the string "C:\Documents and Settings\All Users\Start Menu\Programs\App name" link so

C:\>myprog.exe "C:\Documents and Settings\All Users\Start Menu\Programs\App name" 

the string "C:\Documents and Settings\All Users\Start Menu\Programs\App name"

will be at args[0].

1 Comment

However: the case at hand is that if you call myprog.exe "c:\one\" "two" "three", then args[0] will be c:\one" two three. try it out!
1

To add to what everyone else has already said, It might be an escaping problem. You should escape your backslashes by another backslash.

Should be something like:

C:\>myprog.exe "C:\\Documents and Settings\\All Users\\Start Menu\\Programs\\App name"

Comments

1

I noticed the same annoying issue recently, and decided to write a parser to parse the command line arguments array out myself.

Note: the issue is that the .NET CommandLine Arguments passed to the static void Main(string[] args) function escapes \" and \\. This is by design, since you may actually want to pass an argument that has a quote or backslash in it. One example:

say you wanted to pass the following as a single argument:

-msg:Hey, "Where you at?"

eg.

sampleapp -msg:"Hey, \"Where you at?\""

Would be how to send it with the default behavior.

If you don't see a reason for anyone to have to escape quotes or backslashes for your program, you could utilize your own parser to parse the command line, as below.

IE. [program].exe "C:\test\" arg1 arg2

would have a args[0] = c:\test" arg1 arg2

What you would expect is args[0]=c:\test\ and then args[1]=arg1 and args[2]=arg2.

The below function parses the arguments into a list with this simplified behavior.

Note, arg[0] is the program name using the below code. (You call List.ToArray() to convert the resulting list to a string array.)

protected enum enumParseState : int { StartToken, InQuote, InToken }; public static List<String> ManuallyParseCommandLine() { String CommandLineArgs = Environment.CommandLine.ToString(); Console.WriteLine("Command entered: " + CommandLineArgs); List<String> listArgs = new List<String>(); Regex rWhiteSpace = new Regex("[\\s]"); StringBuilder token = new StringBuilder(); enumParseState eps = enumParseState.StartToken; for (int i = 0; i < CommandLineArgs.Length; i++) { char c = CommandLineArgs[i]; // Console.WriteLine(c.ToString() + ", " + eps); //Looking for beginning of next token if (eps == enumParseState.StartToken) { if (rWhiteSpace.IsMatch(c.ToString())) { //Skip whitespace } else { token.Append(c); eps = enumParseState.InToken; } } else if (eps == enumParseState.InToken) { if (rWhiteSpace.IsMatch(c.ToString())) { Console.WriteLine("Token: [" + token.ToString() + "]"); listArgs.Add(token.ToString().Trim()); eps = enumParseState.StartToken; //Start new token. token.Remove(0, token.Length); } else if (c == '"') { // token.Append(c); eps = enumParseState.InQuote; } else { token.Append(c); eps = enumParseState.InToken; } } //When in a quote, white space is included in the token else if (eps == enumParseState.InQuote) { if (c == '"') { // token.Append(c); eps = enumParseState.InToken; } else { token.Append(c); eps = enumParseState.InQuote; } } } if (token.ToString() != "") { listArgs.Add(token.ToString()); Console.WriteLine("Final Token: " + token.ToString()); } return listArgs; } 

1 Comment

this seems to break if the first character is a quote
1

In response to WWC's answer, Jamezor commented that his code will fail if the first character is a quote.

To fix that problem, you can replace the StartToken case with this:

 if (eps == enumParseState.StartToken) { if (rWhiteSpace.IsMatch(c.ToString())) { //Skip whitespace } else if (c == '"') { eps = enumParseState.InQuote; } else { token.Append(c); eps = enumParseState.InToken; } } 

Comments

0

What exactly is the problem? Anyway here's some general advice:

Make sure your Main method (in Program.cs) is defined as:

void Main(string[] args) 

Then args is an array containing the command-line arguments.

Comments