【问题标题】:Building a command-line programmatically in C#在 C# 中以编程方式构建命令行
【发布时间】:2018-06-23 18:45:58
【问题描述】:

我想知道当您可能有数百个参数时,是否有一个优雅的解决方案来构建命令行以针对 exe 启动。

我想最明显的方法是使用 if/else 语句并构建一个巨大的字符串,但它感觉并不特别优雅。以前有人解决过这个问题吗?

澄清

假设我正在编写一个启动程序 notepad.exe 的程序,该程序本身可以通过接受命令行参数进行配置。

我的程序的唯一目的是构建命令行并启动应用程序。

所以我会有一个表单,其中包含我可以在记事本中设置的所有选项。

WordWrap 的单选按钮是/否。 字体组合框 FontSize 的输入框。

当我点击“启动”按钮时,我会运行“notepad.exe -wordwrap yes -font tahoma -size 8”。

所以我的问题如下:

  • 您将如何处理构建命令行的表单逻辑,您是否有一个包含每个参数的属性的类?并有一个 Build() 方法将它们全部组装起来?
  • 如何将参数传递给可执行文件?

我正在寻找一个优雅的解决方案,而不是这样的:

if (chkWordWrap == true)
 commandline.add("-wordwrap true")

我希望能澄清我的问题:)

【问题讨论】:

  • 所以您只想知道处理命令行参数的最佳实践?
  • 您是否尝试构建 CL args 的排列以用于测试目的?
  • 不,不处理命令行,我想使用我的应用程序来构建命令行并启动接受这些命令的可执行文件:)。
  • 一个例子对理解你想要什么很有帮助。只是将参数连接到一个字符串不需要任何 if/else,那么你到底在说什么?
  • 那么表单将包含启动程序的选项,让我们以记事本为例,假设它使用命令行参数来设置它的选项,您将构建一个命令行,例如:“notepad.exe -wordwrap true -font Tahoma -size 8" 现在在我的应用程序中看到我有一个用于设置字体的下拉菜单,一个用于设置字体大小的输入框,以及一个用于设置自动换行的复选框,当我单击“运行记事本”时,它会构建命令行并执行它:捕获表单数据并将其构建到命令行中的优雅方式是什么。澄清一下,它不适用于记事本 :)

标签: c# command-line


【解决方案1】:

如果您有一个可执行文件在命令行上接受百分之几的参数,那么该特定可执行文件不太可能希望您在命令行上逐字键入这些参数。这些程序中的大多数都可以使用包含其命令行的输入文件。

优雅地:让您的程序编写这样的输入文件并使用Process 以正常方式对程序运行它,类似于以下内容:

Process proc = new Process();
proc.StartInfo.FileName = "externalprogram.exe";
proc.StartInfo.Arguments = "input file here.txt";
proc.Start();

【讨论】:

  • 谢谢,如果它是一个期望其命令行以编程方式提交的程序,因此不接受输入文件怎么办?
  • @toleero:你能定义“程序化”吗?因为即使你不能使用输入文件,你也可以使用proc.StartInfo.Arguments 来包含无数的命令行参数,如果你愿意的话,无论你是启动记事本还是想运行 your-incredibly-many-parameters-program.exe 都不重要.
  • @toleero:所以,我的意思是,这以编程方式为外部程序构建命令行的 .NET 方式。
  • 太棒了,谢谢!你将如何处理表单逻辑?如果您有大量的下拉菜单、单选按钮、组合框,您会拥有一个大类,其属性支持每个命令吗?我猜你可以使用 get/set 来设置它的参数,并为每个命令都有一个“名称”字段,这将是实际的命令?
  • @toleero,这实际上取决于您如何编程以及您对哪些模式感到满意。如果它是一次性应用程序,我可能会为每种类型的 Control 创建扩展方法,例如 GetParamValueGetParamName,并在您遍历表单上的所有控件时调用它。您可以使用控件的属性来包含参数的名称。
【解决方案2】:

您可以尝试拥有具有参数名称和可能值(或基于 UI 元素计算值的方法)的对象列表/映射,然后遍历所有项目并输出参数名称 + 值。

class Parameter
{
 public Parameter(Control control)...
 public string name;
 public bool neededBasedOnControl()...
 public string valueByControl()...
}

List<Parameter> allParameters = new List<Parameter>();
allParameters.Add(new Parameter(myControl42);

...
StringBuilder args;
foreach(var p in allParameter)
{
  if (p.neededBasedOnControl())
  {
    args.Format(p.name, p.valueByControl);
  }
}

【讨论】:

    【解决方案3】:

    我有点不确定您要的是什么,但听起来您正在寻找一种优雅的方式来解析命令行参数。我建议在 CodeProject 上查看这个argument parser。使用解析器,您可以获得如下参数:

    static void Main(string[] args)
    {
        Arguments cmdArgs = new Arguments(args);
    
        Console.WriteLine(cmdArgs["arg_name"]);
    }
    

    【讨论】:

      【解决方案4】:

      要构建命令行字符串,您可以尝试提供 ArgsBuilder 类的“Heleonix.Execution”库: https://github.com/Heleonix/Heleonix.Execution/blob/master/README.md 您可以如下构建命令行字符串:

      var args = ArgsBuilder.By("--", "=")
                  .AddPath("app", "http://www.google.com")
                  .AddArgument("window-size", "300,300", isSized)
                  .AddKey("new-window", isNewWindow);
      
      // Depending on conditions, command line arguments can be like:
      
      // "--app="http://www.google.com" --window-size=300,300 --new-window"
      // "--app="http://www.google.com" --window-size=300,300"
      // "--app="http://www.google.com" --new-window"
      // "--app="http://www.google.com""
      

      您可以添加单独的键、单独的值、键/值参数、路径(默认情况下用“...”包裹)和上述所有内容的列表,并使用条件表达式定义是否应该添加它们(而不是写if 语句)。 您的任何命令行参数都可以使用 ArgsBuilder 本身构建,因此您可以进行嵌套,因为 ArgsBuilder 实例被隐式转换为 System.String,因此无需调用 *.ToString()

      【讨论】:

        猜你喜欢
        • 2014-12-09
        • 2013-08-14
        • 1970-01-01
        • 2012-11-24
        • 2013-01-26
        • 2015-10-01
        • 2012-05-12
        • 2019-10-02
        • 2019-05-07
        相关资源
        最近更新 更多