1. 背景

在.NET开发中,我们经常需要创建命令行应用程序。比如一些工具类应用程序,或者一些自动化脚本等。为了方便用户使用这些应用程序,我们通常会提供一个命令行界面,用户可以通过命令行参数来指定应用程序的行为。

然而,处理命令行参数并不是一件容易的事情。通常情况下,我们需要编写大量的代码来解析命令行参数,并且处理各种不同的情况。这不仅会增加我们的工作量,还会增加应用程序的复杂性。

为了简化这个过程,我们可以使用CommandLine库。这是一个.NET库,专门用于创建命令行应用程序。它提供了一种简单的方法来解析命令行参数,并且可以帮助我们构建一个功能强大的命令行界面。

在之前的文章中,我们在介绍SangServerTool工具时就已经介绍了 CommandLineParser 这个命令行解析库,虽然其使用上非常友好,但是因为这个库积压了很多issue,并且已经很久没有维护了,同时对裁剪的支持也不够好。所以,我们这里介绍一个新的库 CommandLine。

2. CommandLine 介绍

System.CommandLine 是一个由官方维护的为 .NET 应用程序设计的库,专注于简化命令行界面的创建和管理。它旨在帮助开发者构建那些需要解析命令行参数、选项和命令的应用程序,同时提供丰富的功能来支持帮助文本的生成、参数绑定、依赖注入等。

核心功能

  • 命令行参数解析:自动解析用户从命令行输入的参数、选项和命令,减少手动解析的需要。
  • 生成帮助文本:自动生成帮助文本,为用户提供关于如何使用命令行应用的指导。
  • 参数绑定:将命令行输入绑定到应用程序的数据模型或处理逻辑,简化参数处理。
  • 支持自动补全:支持 Tab 键自动补全功能,提高用户使用命令行应用的效率。
  • 响应文件支持:允许用户通过文件输入命令行参数,适用于参数较多的情况。

开发者好处

  • 减少样板代码:开发者可以专注于业务逻辑,而不是处理命令行解析的细节。
  • 易于测试:应用逻辑可以独立于命令行输入分析代码进行测试。
  • 性能优化:库设计考虑到了性能和资源使用,适合开发快速、轻量级的命令行应用。

用户好处

  • 一致性:遵循 POSIX 或 Windows 约定,确保命令行输入的一致性解析。
  • 易用:自动生成的帮助文本和支持的自动补全功能提高了用户体验。

3. 安装CommandLine库

System.CommandLine 库是一个 NuGet 包,可以通过 NuGet 包管理器或者 .NET CLI 来安装。在 Visual Studio 中,可以通过 NuGet 包管理器来搜索并安装 System.CommandLine 包。

dotnet add package System.CommandLine --prerelease

需要注意的是,目前 System.CommandLine 库还处于预览版阶段,所以需要添加 --prerelease 参数来安装预览版的包。

4. 命令定义的使用

这里我们以 SangServerTool 工具为例,来演示如何使用 System.CommandLine 库来定义命令行参数。SangServerTool 含有三个子命令:ddnssslsync,分别对应 DDNS 动态域名解析、SSL 证书申请和远端证书同步功能。

首先,我们需要定义一个 RootCommand 对象,用于表示根命令。

using System.CommandLine;
using System.CommandLine.NamingConventionBinder;

// 创建根命令
var rootCommand = new RootCommand("SangServerTool");

然后,我们可以通过 Command 对象来定义子命令和选项。例如,我们可以定义一个 ddns 子命令,并为其添加选项。

// 定义ddns命令
var ddnsCommand = new Command("ddns", "Set DDNS.");
ddnsCommand.AddOption(new Option<string>(new[] { "--config", "-c" }, "Set config json file.") { IsRequired = true});
ddnsCommand.AddOption(new Option<int>("--delay", () => 0, "How many seconds delay?"));
ddnsCommand.AddOption(new Option<bool>("--del", () => false, "Is delete DDNS?"));
ddnsCommand.AddOption(new Option<bool>("--v6", () => false, "Is ipv6?"));

接着,我们需要定义一个处理命令的委托,并将其与命令绑定。

// 定义处理命令的委托
ddnsCommand.Handler = CommandHandler.Create<string, int, bool, bool>((config, delay, del, v6) =>
{
    // 处理ddns命令
    Console.WriteLine($"config: {config}");
    Console.WriteLine($"delay: {delay}");
    Console.WriteLine($"del: {del}");
    Console.WriteLine($"v6: {v6}");
});

最后,我们将子命令添加到根命令中,并执行命令行解析。

// 将ddns命令添加到根命令
rootCommand.AddCommand(ddnsCommand);
// 解析并执行命令
return await rootCommand.InvokeAsync(args);

最后

关于 System.CommandLine 库的使用,我们在这里只是做了一个简单的介绍,更多的功能和用法可以参考官方文档

虽然 System.CommandLine 提供了丰富的功能,但它仍然处于预览版阶段,这意味着在正式发布之前,它可能会发生重大更改。因此,开发者在使用时需要注意版本更新和兼容性问题。不过,考虑到它是由官方维护的库,未来应该会得到更好的支持和维护。

05-25 00:27