System.CommandLine是微软官方提供的命令行解析库,专门用于简化C#命令行应用的开发流程,它内置了参数解析、命令管理、帮助信息生成等能力,不需要开发者手动处理复杂的字符串拆分和参数匹配逻辑。

基础环境准备
首先需要在项目中引入System.CommandLine的NuGet包,目前最新的稳定版本可以直接通过包管理器安装,安装完成后即可在代码中引用相关命名空间。
// 引入必要的命名空间 using System.CommandLine; using System.CommandLine.Invocation;
定义基础命令和参数
System.CommandLine的核心逻辑是先定义命令和参数,再绑定对应的执行逻辑。最基础的命令行工具可以只有一个根命令,搭配若干参数。
定义根命令
根命令是整个命令行工具的入口,我们可以通过RootCommand类来创建根命令,同时设置命令的描述信息,这些信息会自动出现在工具生成的帮助文档中。
// 创建根命令,设置命令描述
var rootCommand = new RootCommand("这是一个示例命令行工具,用于演示System.CommandLine的基础用法");
添加参数
参数分为选项(Option)和参数(Argument)两类,选项通常以--或-开头,参数则是位置固定的输入值。我们可以为参数设置名称、描述、是否必填、默认值等属性。
// 定义一个字符串选项,名称为--name,描述为"输入用户名称",默认值为"默认用户"
var nameOption = new Option<string>(
name: "--name",
description: "输入用户名称",
getDefaultValue: () => "默认用户"
);
// 定义一个整数参数,名称为input-number,描述为"输入一个整数",设置为必填
var numberArgument = new Argument<int>(
name: "input-number",
description: "输入一个整数"
);
numberArgument.Arity = ArgumentArity.ExactlyOne; // 设置参数必须传入一个值
定义好参数后,需要将参数添加到根命令中,然后绑定参数的处理逻辑。
// 将选项和参数添加到根命令
rootCommand.AddOption(nameOption);
rootCommand.AddArgument(numberArgument);
// 绑定根命令的处理逻辑
rootCommand.SetHandler((string name, int number) =>
{
Console.WriteLine($"接收到的用户名称是:{name}");
Console.WriteLine($"接收到的整数是:{number}");
Console.WriteLine($"计算结果:{number} * 2 = {number * 2}");
}, nameOption, numberArgument);
执行命令
最后只需要调用根命令的InvokeAsync方法,传入命令行参数即可执行对应的逻辑,通常会把args直接传入。
// 执行命令,传入命令行参数 return await rootCommand.InvokeAsync(args);
此时如果运行程序并输入test.exe --name 张三 10,就会输出对应的处理结果,如果输入test.exe --help,会自动生成所有命令和参数的说明信息。
添加子命令
当命令行工具功能较多时,单一的根命令会导致参数混乱,此时可以使用子命令来拆分功能。比如我们可以添加一个add子命令用于计算加法,一个sub子命令用于计算减法。
// 创建add子命令
var addCommand = new Command("add", "计算两个数字的和");
// 为add子命令定义两个必填的整数参数
var addArg1 = new Argument<int>("num1", "第一个加数");
var addArg2 = new Argument<int>("num2", "第二个加数");
addCommand.AddArgument(addArg1);
addCommand.AddArgument(addArg2);
// 绑定add子命令的处理逻辑
addCommand.SetHandler((int num1, int num2) =>
{
Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
}, addArg1, addArg2);
// 创建sub子命令
var subCommand = new Command("sub", "计算两个数字的差");
var subArg1 = new Argument<int>("num1", "被减数");
var subArg2 = new Argument<int>("num2", "减数");
subCommand.AddArgument(subArg1);
subCommand.AddArgument(subArg2);
subCommand.SetHandler((int num1, int num2) =>
{
Console.WriteLine($"{num1} - {num2} = {num1 - num2}");
}, subArg1, subArg2);
// 将两个子命令添加到根命令
rootCommand.AddCommand(addCommand);
rootCommand.AddCommand(subCommand);
添加子命令后,运行test.exe add 5 3会输出8,运行test.exe sub 10 4会输出6,帮助信息也会自动包含子命令的说明。
参数校验和全局选项
System.CommandLine支持自定义参数校验逻辑,也支持定义全局选项,所有子命令都可以使用全局选项。比如我们可以定义一个--verbose全局选项,用于控制是否输出详细日志。
// 定义全局选项--verbose,用于控制详细日志输出
var verboseOption = new Option<bool>(
name: "--verbose",
description: "是否输出详细日志",
getDefaultValue: () => false
);
// 将全局选项添加到根命令,所有子命令都可以使用
rootCommand.AddGlobalOption(verboseOption);
// 修改add子命令的处理逻辑,使用verbose选项
addCommand.SetHandler((int num1, int num2, bool verbose) =>
{
if (verbose)
{
Console.WriteLine("开始执行加法计算");
Console.WriteLine($"第一个加数:{num1},第二个加数:{num2}");
}
Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
if (verbose)
{
Console.WriteLine("加法计算执行完成");
}
}, addArg1, addArg2, verboseOption);
如果需要校验参数,比如要求输入的数字必须大于0,可以在参数定义时添加校验逻辑:
// 为numberArgument添加校验,要求输入的数字必须大于0
numberArgument.AddValidator(result =>
{
var value = result.GetValueOrDefault<int>();
if (value <= 0)
{
result.ErrorMessage = "输入的整数必须大于0";
}
});
当输入不符合校验规则时,工具会自动输出错误信息,不会执行对应的处理逻辑。
完整示例代码
以下是整合了上述所有功能的完整示例代码,可以直接复制到项目中运行测试。
using System.CommandLine;
using System.CommandLine.Invocation;
class Program
{
static async Task<int> Main(string[] args)
{
// 创建根命令
var rootCommand = new RootCommand("这是一个示例命令行工具,用于演示System.CommandLine的完整用法");
// 定义根命令的参数
var nameOption = new Option<string>(
name: "--name",
description: "输入用户名称",
getDefaultValue: () => "默认用户"
);
var numberArgument = new Argument<int>(
name: "input-number",
description: "输入一个大于0的整数"
);
numberArgument.Arity = ArgumentArity.ExactlyOne;
// 添加参数校验
numberArgument.AddValidator(result =>
{
var value = result.GetValueOrDefault<int>();
if (value <= 0)
{
result.ErrorMessage = "输入的整数必须大于0";
}
});
rootCommand.AddOption(nameOption);
rootCommand.AddArgument(numberArgument);
// 绑定根命令处理逻辑
rootCommand.SetHandler((string name, int number) =>
{
Console.WriteLine($"接收到的用户名称是:{name}");
Console.WriteLine($"接收到的整数是:{number}");
Console.WriteLine($"计算结果:{number} * 2 = {number * 2}");
}, nameOption, numberArgument);
// 定义全局选项
var verboseOption = new Option<bool>(
name: "--verbose",
description: "是否输出详细日志",
getDefaultValue: () => false
);
rootCommand.AddGlobalOption(verboseOption);
// 定义add子命令
var addCommand = new Command("add", "计算两个数字的和");
var addArg1 = new Argument<int>("num1", "第一个加数");
var addArg2 = new Argument<int>("num2", "第二个加数");
addCommand.AddArgument(addArg1);
addCommand.AddArgument(addArg2);
addCommand.SetHandler((int num1, int num2, bool verbose) =>
{
if (verbose)
{
Console.WriteLine("开始执行加法计算");
Console.WriteLine($"第一个加数:{num1},第二个加数:{num2}");
}
Console.WriteLine($"{num1} + {num2} = {num1 + num2}");
if (verbose)
{
Console.WriteLine("加法计算执行完成");
}
}, addArg1, addArg2, verboseOption);
// 定义sub子命令
var subCommand = new Command("sub", "计算两个数字的差");
var subArg1 = new Argument<int>("num1", "被减数");
var subArg2 = new Argument<int>("num2", "减数");
subCommand.AddArgument(subArg1);
subCommand.AddArgument(subArg2);
subCommand.SetHandler((int num1, int num2, bool verbose) =>
{
if (verbose)
{
Console.WriteLine("开始执行减法计算");
Console.WriteLine($"被减数:{num1},减数:{num2}");
}
Console.WriteLine($"{num1} - {num2} = {num1 - num2}");
if (verbose)
{
Console.WriteLine("减法计算执行完成");
}
}, subArg1, subArg2, verboseOption);
// 添加子命令到根命令
rootCommand.AddCommand(addCommand);
rootCommand.AddCommand(subCommand);
// 执行命令
return await rootCommand.InvokeAsync(args);
}
}
System_CommandLineC#命令行工具参数解析修改时间:2026-07-03 08:09:39