在 C# 中传递命令行参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/653563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 11:59:37  来源:igfitidea点击:

Passing command-line arguments in C#

c#command-line-arguments

提问by

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

我正在尝试将命令行参数传递给 C# 应用程序,但我在传递类似这样的内容时遇到问题

"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.

问题是我可以正确地获得第一个和第二个参数,但最后一个它作为C:\Documents.

Any help?

有什么帮助吗?

采纳答案by Henk Holterman

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

第 2 部分,我又进行了一些测试

"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:

谷歌的一个小动作从Jon Galloway博客中提供了一些见解,基本规则是:

  • the backslash is the escape character
  • always escape quotes
  • only escape backslashes when they precede a quote.
  • 反斜杠是转义字符
  • 总是逃避报价
  • 只有在引用之前转义反斜杠。

回答by Ian Kemp

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

究竟是什么问题?无论如何,这里有一些一般性建议:

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

确保您的 Main 方法(在 Program.cs 中)定义为:

void Main(string[] args)

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

然后 args 是一个包含命令行参数的数组。

回答by Johnno Nolan

To add Ian Kemp's answer

添加 Ian Kemp 的答案

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

如果您的程序集名为“myProg.exe”并且您传入字符串“C:\Documents and Settings\All Users\Start Menu\Programs\App name”链接,则

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"

字符串“C:\Documents and Settings\All Users\Start Menu\Programs\App name”

will be at args[0].

将在 args[0]。

回答by Aamir

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"

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

回答by WWC

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:

注意:问题是传递给 static void Main(string[] args) 函数的 .NET CommandLine Arguments 转义了 \" 和 \\。这是设计使然,因为您可能实际上想要传递一个带有引号或反斜杠在里面。一个例子:

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

假设您想将以下内容作为单个参数传递:

-msg:Hey, "Where you at?"

-msg:嘿,“你在哪里?”

eg.

例如。

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

sampleapp -msg:"嘿,\"你在哪里?\""

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

IE。[程序].exe "C:\test\" arg1 arg2

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

会有一个 args[0] = c:\test" arg1 arg2

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

您所期望的是 args[0]=c:\test\,然后是 args[1]=arg1 和 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.)

注意,arg[0] 是使用以下代码的程序名称。(您调用 List.ToArray() 将结果列表转换为字符串数组。)

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;
}

回答by guesser

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

在回应 WWC 的回答时,Jamezor 评论说,如果第一个字符是引号,他的代码将失败。

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

为了解决这个问题,你可以用这个替换 StartToken 案例:

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