Passing command-line arguments in C#
-
19-08-2019 - |
Question
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?
Solution
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.
OTHER TIPS
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].
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"
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;
}
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;
}
}
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.