简体   繁体   English

解析 C# 中的命令行参数/选项

[英]Parse command line arguments/options in C#

I have a console application with some arguments and options so I would like to use a free third-party library.我有一个带有一些 arguments 和选项的控制台应用程序,所以我想使用免费的第三方库。

I have found two libraries for this purpose: NDesk.Options and Command Line Parser Library为此,我找到了两个库: NDesk.OptionsCommand Line Parser Library

Finally I have decided to use Command Line Parser Library because it is clearer using properties so I have downloaded it and added a reference to it.最后我决定使用 Command Line Parser Library,因为它使用属性更清晰,所以我下载了它并添加了对它的引用。

The problem is that when adding the reference to my .NET Framework 3.5 project I get a warning icon.问题是,在添加对我的 .NET Framework 3.5 项目的引用时,我得到一个警告图标。 From the above page where I have downloaded it, it says that compatibility is .NET Framework 3.5+ so I understand 3.5 is compatible, am I right?从我下载的上面的页面上,它说兼容性是 .NET Framework 3.5+,所以我知道 3.5 是兼容的,对吗? If not which previous version of it is compatible with .NET Framework 3.5?如果不是,它的哪个先前版本与 .NET Framework 3.5 兼容?

You can also use the new Microsoft CommandLineUtils library. 您也可以使用新的Microsoft CommandLineUtils库。 The nuget package is here, but only for .NET Core or Framrwork 4.5.2. nuget软件包在这里,但仅适用于.NET Core或Framrwork 4.5.2。 But you can download the source code (only 7 files) and include in your projet. 但是您可以下载源代码(仅7个文件)并包含在projet中。 For the Framework 3.5, you have only 2 compilation errors to solve: remove an extra method (using Tasks) and remove one line (in HandleUnexpectedArg). 对于Framework 3.5,您只需解决2个编译错误:删除一个额外的方法(使用Tasks)并删除一行(在HandleUnexpectedArg中)。

To use this library, find here a first sample: 要使用此库,请在此处找到第一个示例:

static void Main(string[] args)
{
    var cmd = new CommandLineApplication();
    var argAdd = cmd.Option("-a | --add <value>", "Add a new item", CommandOptionType.SingleValue);

    cmd.OnExecute(() =>
    {
        Console.WriteLine(argAdd.Value());
        return 0;
    });

    cmd.HelpOption("-? | -h | --help");
    cmd.Execute(args);            
}

McMaster.Extensions.CommandLineUtils is the best command line parser for c# that I've used. McMaster.Extensions.CommandLineUtils 是我用过的最好的 c# 命令行解析器。 I especially like that it supports subcommands well.我特别喜欢它很好地支持子命令。

Source code is here: https://github.com/natemcmaster/CommandLineUtils源代码在这里: https://github.com/natemcmaster/CommandLineUtils

dotnet add package McMaster.Extensions.CommandLineUtils

This is a simple example of how to use it using attributes:这是一个如何使用属性使用它的简单示例:

using System;
using McMaster.Extensions.CommandLineUtils;

public class Program
{
    public static int Main(string[] args)
        => CommandLineApplication.Execute<Program>(args);

    [Option(Description = "The subject")]
    public string Subject { get; } = "world";

    [Option(ShortName = "n")]
    public int Count { get; } = 1;

    private void OnExecute()
    {
        for (var i = 0; i < Count; i++)
        {
            Console.WriteLine($"Hello {Subject}!");
        }
    }
}

Or you could use a builder:或者您可以使用构建器:

using System;
using McMaster.Extensions.CommandLineUtils;

var app = new CommandLineApplication();

app.HelpOption();

var subject = app.Option("-s|--subject <SUBJECT>", "The subject", CommandOptionType.SingleValue);
subject.DefaultValue = "world";

var repeat = app.Option<int>("-n|--count <N>", "Repeat", CommandOptionType.SingleValue);
repeat.DefaultValue = 1;

app.OnExecute(() =>
{
    for (var i = 0; i < repeat.ParsedValue; i++)
    {
        Console.WriteLine($"Hello {subject.Value()}!");
    }
});

return app.Execute(args);

Microsoft have also been working on a command line parser: https://github.com/do.net/command-line-api but it's been in preview for ages.微软也一直致力于命令行解析器: https://github.com/do.net/command-line-api但它已经预览了很长时间。

I recommend FluentArgs (see: https://github.com/kutoga/FluentArgs ). 我推荐FluentArgs (请参阅: https : //github.com/kutoga/FluentArgs )。 I think it is very easy to use: 我认为这很容易使用:

namespace Example
{
    using System;
    using System.Threading.Tasks;
    using FluentArgs;

    public static class Program
    {
        public static Task Main(string[] args)
        {
            return FluentArgsBuilder.New()
                .DefaultConfigsWithAppDescription("An app to convert png files to jpg files.")
                .Parameter("-i", "--input")
                    .WithDescription("Input png file")
                    .WithExamples("input.png")
                    .IsRequired()
                .Parameter("-o", "--output")
                    .WithDescription("Output jpg file")
                    .WithExamples("output.jpg")
                    .IsRequired()
                .Parameter<ushort>("-q", "--quality")
                    .WithDescription("Quality of the conversion")
                    .WithValidation(n => n >= 0 && n <= 100)
                    .IsOptionalWithDefault(50)
                .Call(quality => outputFile => inputFile =>
                {
                    /* ... */
                    Console.WriteLine($"Convert {inputFile} to {outputFile} with quality {quality}...");
                    /* ... */
                    return Task.CompletedTask;
                })
                .ParseAsync(args);
        }
    }
}

There are many other examples on the github page. github页面上还有许多其他示例。

System.CommandLine might do the trick. System.CommandLine可能会成功。 Though as of November 2022 it is still in beta.尽管截至 2022 年 11 月,它仍处于测试阶段。 I suppose the .NET team is going to include it in some upcoming .NET framework release.我想 .NET 团队将把它包含在一些即将发布的 .NET 框架版本中。

https://github.com/do.net/runtime/issues/68578 https://www.nuget.org/packages/System.CommandLine https://github.com/do.net/runtime/issues/68578 https://www.nuget.org/packages/System.CommandLine

If you're looking for a third-party library to help you parse command-line arguments and options in C#, you might want to check out the TreeBasedCli library.如果您正在寻找第三方库来帮助您解析命令行 arguments 和 C# 中的选项,您可能需要查看TreeBasedCli库。 It is a C# library designed to simplify the process of creating command-line interfaces (CLIs) with nested subcommands, and offers a number of benefits for both developers and users.它是一个 C# 库,旨在简化使用嵌套子命令创建命令行界面 (CLI) 的过程,并为开发人员和用户提供许多好处。

One of the key features of TreeBasedCli is its modular structure, which allows you to easily organize and structure your CLI's functionality using leaf and branch commands. TreeBasedCli 的关键特性之一是其模块化结构,它允许您使用叶和分支命令轻松地组织和构建 CLI 的功能。 Leaf commands represent specific actions that can be performed, and are implemented as individual classes with their own command definition, input parser, and asynchronous handler.叶命令表示可以执行的特定操作,并作为具有自己的命令定义、输入解析器和异步处理程序的单独类来实现。 Branch commands, on the other hand, represent a group of subcommands and do not have an associated action.另一方面,分支命令表示一组子命令并且没有关联的操作。 This allows you to easily create complex CLIs with multiple levels of nesting.这使您可以轻松创建具有多层嵌套的复杂 CLI。

Another benefit of TreeBasedCli is its support for asynchronous command execution. TreeBasedCli 的另一个好处是它支持异步命令执行。 It also includes a lightweight Dependency Injection (DI) interface, allowing you to use your preferred method of DI type resolution.它还包括一个轻量级的依赖注入 (DI) 接口,允许您使用您喜欢的 DI 类型解析方法。

public class CreateCatCommand :
    LeafCommand<
        CreateCatCommand.Arguments,
        CreateCatCommand.Parser,
        CreateCatCommand.Handler>
{
    private const string NameLabel = "--name";

    public CreateCatCommand() : base(
        label: "create-cat",
        description: new[]
        {
            "Prints out a cat."
        },
        options: new[]
        {
            new CommandOption(
                label: NameLabel,
                description: new[]
                {
                    "Required. The name of the cat to print."
                }
            ),
        },
        DependencyInjectionService.Instance)
    { }

    public record Arguments(string CatName) : IParsedCommandArguments;

    public class Parser : ICommandArgumentParser<Arguments>
    {
        public IParseResult<Arguments> Parse(CommandArguments arguments)
        {
            string name = arguments.GetArgument(NameLabel).ExpectedAsSingleValue();

            var result = new Arguments(
                CatName: name
            );

            return new SuccessfulParseResult<Arguments>(result);
        }
    }

    public class Handler : ICommandHandler<Arguments>
    {
        private readonly IUserInterface userInterface;

        public Handler(IUserInterface userInterface)
        {
            this.userInterface = userInterface;
        }

        public Task HandleAsync(Arguments arguments, LeafCommand _)
        {
            this.userInterface.WriteLine($"I am a cat 😸 with the name {arguments.CatName}!");
            return Task.CompletedTask;
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM