在构建接受参数的控制台应用程序时,可以使用传递给Main的参数(string[] args)。
在过去,我只是简单地索引/循环该数组,并做了一些正则表达式来提取值。然而,当命令变得更加复杂时,解析就会变得非常糟糕。
我感兴趣的是:
你使用的库 你使用的模式
假设命令总是遵循常见的标准,比如这里回答的。
在构建接受参数的控制台应用程序时,可以使用传递给Main的参数(string[] args)。
在过去,我只是简单地索引/循环该数组,并做了一些正则表达式来提取值。然而,当命令变得更加复杂时,解析就会变得非常糟糕。
我感兴趣的是:
你使用的库 你使用的模式
假设命令总是遵循常见的标准,比如这里回答的。
WPF TestApi库提供了c#开发中最好的命令行解析器之一。我强烈推荐你去看看,这是Ivo Manolov关于API的博客:
// EXAMPLE #2:
// Sample for parsing the following command-line:
// Test.exe /verbose /runId=10
// This sample declares a class in which the strongly-
// typed arguments are populated
public class CommandLineArguments
{
bool? Verbose { get; set; }
int? RunId { get; set; }
}
CommandLineArguments a = new CommandLineArguments();
CommandLineParser.ParseArguments(args, a);
http://www.codeplex.com/commonlibrarynet上有一个命令行参数解析器
它可以使用 1. 属性 2. 显式的调用 3.单行多个参数或字符串数组
它可以处理以下事情:
-config:Qa -startdate:${today} -region:'New York' Settings01
它很容易使用。
这是我基于Novell Options类编写的处理程序。
它针对的是执行while (input !="exit")样式循环的控制台应用程序,例如一个交互式控制台,例如FTP控制台。
使用示例:
static void Main(string[] args)
{
// Setup
CommandHandler handler = new CommandHandler();
CommandOptions options = new CommandOptions();
// Add some commands. Use the v syntax for passing arguments
options.Add("show", handler.Show)
.Add("connect", v => handler.Connect(v))
.Add("dir", handler.Dir);
// Read lines
System.Console.Write(">");
string input = System.Console.ReadLine();
while (input != "quit" && input != "exit")
{
if (input == "cls" || input == "clear")
{
System.Console.Clear();
}
else
{
if (!string.IsNullOrEmpty(input))
{
if (options.Parse(input))
{
System.Console.WriteLine(handler.OutputMessage);
}
else
{
System.Console.WriteLine("I didn't understand that command");
}
}
}
System.Console.Write(">");
input = System.Console.ReadLine();
}
}
来源是:
/// <summary>
/// A class for parsing commands inside a tool. Based on Novell Options class (http://www.ndesk.org/Options).
/// </summary>
public class CommandOptions
{
private Dictionary<string, Action<string[]>> _actions;
private Dictionary<string, Action> _actionsNoParams;
/// <summary>
/// Initializes a new instance of the <see cref="CommandOptions"/> class.
/// </summary>
public CommandOptions()
{
_actions = new Dictionary<string, Action<string[]>>();
_actionsNoParams = new Dictionary<string, Action>();
}
/// <summary>
/// Adds a command option and an action to perform when the command is found.
/// </summary>
/// <param name="name">The name of the command.</param>
/// <param name="action">An action delegate</param>
/// <returns>The current CommandOptions instance.</returns>
public CommandOptions Add(string name, Action action)
{
_actionsNoParams.Add(name, action);
return this;
}
/// <summary>
/// Adds a command option and an action (with parameter) to perform when the command is found.
/// </summary>
/// <param name="name">The name of the command.</param>
/// <param name="action">An action delegate that has one parameter - string[] args.</param>
/// <returns>The current CommandOptions instance.</returns>
public CommandOptions Add(string name, Action<string[]> action)
{
_actions.Add(name, action);
return this;
}
/// <summary>
/// Parses the text command and calls any actions associated with the command.
/// </summary>
/// <param name="command">The text command, e.g "show databases"</param>
public bool Parse(string command)
{
if (command.IndexOf(" ") == -1)
{
// No params
foreach (string key in _actionsNoParams.Keys)
{
if (command == key)
{
_actionsNoParams[key].Invoke();
return true;
}
}
}
else
{
// Params
foreach (string key in _actions.Keys)
{
if (command.StartsWith(key) && command.Length > key.Length)
{
string options = command.Substring(key.Length);
options = options.Trim();
string[] parts = options.Split(' ');
_actions[key].Invoke(parts);
return true;
}
}
}
return false;
}
}
我强烈建议使用NDesk。选项(文档)和/或Mono。选项(相同的API,不同的名称空间)。文档中的一个例子:
bool show_help = false;
List<string> names = new List<string> ();
int repeat = 1;
var p = new OptionSet () {
{ "n|name=", "the {NAME} of someone to greet.",
v => names.Add (v) },
{ "r|repeat=",
"the number of {TIMES} to repeat the greeting.\n" +
"this must be an integer.",
(int v) => repeat = v },
{ "v", "increase debug message verbosity",
v => { if (v != null) ++verbosity; } },
{ "h|help", "show this message and exit",
v => show_help = v != null },
};
List<string> extra;
try {
extra = p.Parse (args);
}
catch (OptionException e) {
Console.Write ("greet: ");
Console.WriteLine (e.Message);
Console.WriteLine ("Try `greet --help' for more information.");
return;
}
这个问题有很多解决方案。为了完整性和提供替代方案,如果有人需要,我在我的谷歌代码库中添加了两个有用的类的答案。
第一个是ArgumentList,它只负责解析命令行参数。它收集由开关'/x:y'或'-x=y'定义的名值对,还收集'未命名'条目列表。它的基本用法在这里讨论,查看类在这里。
第二部分是CommandInterpreter,它从. net类中创建一个功能齐全的命令行应用程序。举个例子:
using CSharpTest.Net.Commands;
static class Program
{
static void Main(string[] args)
{
new CommandInterpreter(new Commands()).Run(args);
}
//example ‘Commands’ class:
class Commands
{
public int SomeValue { get; set; }
public void DoSomething(string svalue, int ivalue)
{ ... }
使用上面的示例代码,您可以运行以下代码:
exe DoSomething“字符串值
——或——
Program.exe dosomething /ivalue=5 -svalue:"字符串值"
它就是这么简单,也有你想要的那么复杂。您可以查看源代码、查看帮助或下载二进制文件。
看起来每个人都有自己的宠物命令行解析器,我最好也添加我的:)。
http://bizark.codeplex.com/
这个库包含一个命令行解析器,它将使用命令行中的值初始化一个类。它有很多功能(我已经建立了很多年了)。
从文档中…
怪诞框架中的命令行解析具有以下关键特性:
Automatic initialization: Class properties are automatically set based on the command-line arguments. Default properties: Send in a value without specifying the property name. Value conversion: Uses the powerful ConvertEx class also included in BizArk to convert values to the proper type. Boolean flags: Flags can be specified by simply using the argument (ex, /b for true and /b- for false) or by adding the value true/false, yes/no, etc. Argument arrays: Simply add multiple values after the command-line name to set a property that is defined as an array. Ex, /x 1 2 3 will populate x with the array { 1, 2, 3 } (assuming x is defined as an array of integers). Command-line aliases: A property can support multiple command-line aliases for it. For example, Help uses the alias ?. Partial name recognition: You don’t need to spell out the full name or alias, just spell enough for the parser to disambiguate the property/alias from the others. Supports ClickOnce: Can initialize properties even when they are specified as the query string in a URL for ClickOnce deployed applications. The command-line initialization method will detect if it is running as ClickOnce or not so your code doesn’t need to change when using it. Automatically creates /? help: This includes nice formatting that takes into account the width of the console. Load/Save command-line arguments to a file: This is especially useful if you have multiple large, complex sets of command-line arguments that you want to run multiple times.
我个人最喜欢的是Peter palota的http://www.codeproject.com/KB/recipes/plossum_commandline.aspx:
[CommandLineManager(ApplicationName="Hello World",
Copyright="Copyright (c) Peter Palotas")]
class Options
{
[CommandLineOption(Description="Displays this help text")]
public bool Help = false;
[CommandLineOption(Description = "Specifies the input file", MinOccurs=1)]
public string Name
{
get { return mName; }
set
{
if (String.IsNullOrEmpty(value))
throw new InvalidOptionValueException(
"The name must not be empty", false);
mName = value;
}
}
private string mName;
}
我最近遇到了FubuCore命令行解析实现,我真的很喜欢它,原因是:
it's easy to use - although I couldn't find a documentation for it, the FubuCore solution also provides a project containing a nice set of Unit Tests that speak more about the functionality than any documentation could it has a nice object oriented design, no code repetition or other such things that I used to have in my command line parsing apps it's declarative: you basically write classes for the Commands and sets of parameters and decorate them with attributes to set various options (e.g. name, description, mandatory/optional) the library even prints a nice Usage Graph, based on these definitions
下面是一个简单的例子说明如何使用它。为了说明用法,我写了一个简单的实用程序,它有两个命令: - add(将一个对象添加到列表中-一个对象由一个名称(字符串),值(int)和一个布尔标志组成) - list(列出当前添加的所有对象)
首先,我为'add'命令写了一个Command类:
[Usage("add", "Adds an object to the list")]
[CommandDescription("Add object", Name = "add")]
public class AddCommand : FubuCommand<CommandInput>
{
public override bool Execute(CommandInput input)
{
State.Objects.Add(input); // add the new object to an in-memory collection
return true;
}
}
这个命令接受一个commandput实例作为参数,所以我下面定义它:
public class CommandInput
{
[RequiredUsage("add"), Description("The name of the object to add")]
public string ObjectName { get; set; }
[ValidUsage("add")]
[Description("The value of the object to add")]
public int ObjectValue { get; set; }
[Description("Multiply the value by -1")]
[ValidUsage("add")]
[FlagAlias("nv")]
public bool NegateValueFlag { get; set; }
}
下一个命令是'list',实现如下:
[Usage("list", "List the objects we have so far")]
[CommandDescription("List objects", Name = "list")]
public class ListCommand : FubuCommand<NullInput>
{
public override bool Execute(NullInput input)
{
State.Objects.ForEach(Console.WriteLine);
return false;
}
}
'list'命令不带参数,所以我定义了一个NullInput类:
public class NullInput { }
现在剩下的就是在Main()方法中把它连接起来,就像这样:
static void Main(string[] args)
{
var factory = new CommandFactory();
factory.RegisterCommands(typeof(Program).Assembly);
var executor = new CommandExecutor(factory);
executor.Execute(args);
}
程序按预期工作,在任何命令无效的情况下打印正确用法的提示:
------------------------
Available commands:
------------------------
add -> Add object
list -> List objects
------------------------
下面是'add'命令的用法示例:
Usages for 'add' (Add object)
add <objectname> [-nv]
-------------------------------------------------
Arguments
-------------------------------------------------
objectname -> The name of the object to add
objectvalue -> The value of the object to add
-------------------------------------------------
-------------------------------------
Flags
-------------------------------------
[-nv] -> Multiply the value by -1
-------------------------------------
请使用apache commons cli API的。net端口。这很有效。
http://sourceforge.net/projects/dotnetcli/
以及用于概念和介绍的原始API
http://commons.apache.org/cli/
一个非常简单易于使用的命令行解析专用类,它支持默认参数。
class CommandLineArgs
{
public static CommandLineArgs I
{
get
{
return m_instance;
}
}
public string argAsString( string argName )
{
if (m_args.ContainsKey(argName)) {
return m_args[argName];
}
else return "";
}
public long argAsLong(string argName)
{
if (m_args.ContainsKey(argName))
{
return Convert.ToInt64(m_args[argName]);
}
else return 0;
}
public double argAsDouble(string argName)
{
if (m_args.ContainsKey(argName))
{
return Convert.ToDouble(m_args[argName]);
}
else return 0;
}
public void parseArgs(string[] args, string defaultArgs )
{
m_args = new Dictionary<string, string>();
parseDefaults(defaultArgs );
foreach (string arg in args)
{
string[] words = arg.Split('=');
m_args[words[0]] = words[1];
}
}
private void parseDefaults(string defaultArgs )
{
if ( defaultArgs == "" ) return;
string[] args = defaultArgs.Split(';');
foreach (string arg in args)
{
string[] words = arg.Split('=');
m_args[words[0]] = words[1];
}
}
private Dictionary<string, string> m_args = null;
static readonly CommandLineArgs m_instance = new CommandLineArgs();
}
class Program
{
static void Main(string[] args)
{
CommandLineArgs.I.parseArgs(args, "myStringArg=defaultVal;someLong=12");
Console.WriteLine("Arg myStringArg : '{0}' ", CommandLineArgs.I.argAsString("myStringArg"));
Console.WriteLine("Arg someLong : '{0}' ", CommandLineArgs.I.argAsLong("someLong"));
}
}
我非常喜欢命令行解析器库(http://commandline.codeplex.com/)。它有一个非常简单和优雅的方式来通过属性设置参数:
class Options
{
[Option("i", "input", Required = true, HelpText = "Input file to read.")]
public string InputFile { get; set; }
[Option(null, "length", HelpText = "The maximum number of bytes to process.")]
public int MaximumLenght { get; set; }
[Option("v", null, HelpText = "Print details during execution.")]
public bool Verbose { get; set; }
[HelpOption(HelpText = "Display this help screen.")]
public string GetUsage()
{
var usage = new StringBuilder();
usage.AppendLine("Quickstart Application 1.0");
usage.AppendLine("Read user manual for usage instructions...");
return usage.ToString();
}
}
你可能会喜欢我的地毯。Cmd
易于使用和扩展的命令行参数解析器。句柄:Bool,加/减,字符串,字符串列表,CSV,枚举。
内置/?帮助模式。
内置/??'和'/?D'文档生成器模式。
static void Main(string[] args)
{
// create the argument parser
ArgumentParser parser = new ArgumentParser("ArgumentExample", "Example of argument parsing");
// create the argument for a string
StringArgument StringArg = new StringArgument("String", "Example string argument", "This argument demonstrates string arguments");
// add the argument to the parser
parser.Add("/", "String", StringArg);
// parse arguemnts
parser.Parse(args);
// did the parser detect a /? argument
if (parser.HelpMode == false)
{
// was the string argument defined
if (StringArg.Defined == true)
{
// write its value
RC.WriteLine("String argument was defined");
RC.WriteLine(StringArg.Value);
}
}
}
编辑:这是我的项目,因此这个答案不应该被视为来自第三方的认可。也就是说,我确实在我编写的每个基于命令行的程序中使用它,它是开源的,我希望其他人可以从中受益。
CLAP(命令行参数解析器)有一个可用的API,并且有很好的文档。创建一个方法,注释参数。https://github.com/adrianaisemberg/CLAP
Powershell Commandlets。
powershell根据命令行中指定的属性进行解析,支持验证、参数集、流水线、错误报告、帮助,最好的是返回。net对象供其他命令行使用。
我发现了一些有用的入门链接:
快速入门教程 MSDN编程指南 MSDN上的Namespace引用