title author date CreateTime categories
dotnet 使用 System.CommandLine 写命令行程序
lindexi
2019-08-31 16:55:58 +0800
2019-04-20 17:22:15 +0800
dotnet

在写命令行程序的时候,会遇到命令行解析的问题,以及参数的使用和规范化等坑。现在社区开源了命令行项目,可以帮助小伙伴快速开发命令行程序,支持自动的命令行解析和规范的参数

我写过一篇关于命令行解析的博客C#命令行解析工具 但是这个方法不是很好用

在社区找到了 System.CommandLine 这是一个还在开发过程的很好用的一个库,里面用了很多很黑的写法

我创建了一个项目,我删除了原来的 Main 函数,使用下面的代码替换原来的 Main 函数,然后居然是可以编译通过运行的

        static void Main(string name, string text)
{
Console.WriteLine($"{name}{text}");
}

当然在开始之前我需要安装两个 Nuget 库

  • System.CommandLine.DragonFruit
  • System.CommandLine.Rendering

可以通过创建一个 dotnet core 项目,编辑项目文件,添加下面代码

  <ItemGroup>
<PackageReference Include="System.CommandLine.DragonFruit" Version="0.2.0-alpha.19174.3" />
<PackageReference Include="System.CommandLine.Rendering" Version="0.2.0-alpha.19174.3" />
</ItemGroup>

现在尝试使用 dotnet 命令行运行,请使用下面代码

dotnet run -- --name 林德熙 --text 是逗比

在 dotnet 命令使用 -- 分割调用的参数,也就是在 -- 后面的参数将会传递到程序里面

于是就相当于运行了测试项目,传入参数 --name 林德熙 --text 是逗比 可以看到输出

林德熙是逗比

这个例子的项目请看测试程序

当然命令行的参数写法有很多,上面的程序也支持下面的参数

dotnet run -- --name:林德熙 --text:是逗比

当然一个命令行程序,如果就一个 exe 发给小伙伴,那么小伙伴怎么知道如何使用?在软件工程里面,在这一行默认的就是输入 --help 就输出帮助信息

于是我在主函数添加一点注释

        /// <summary>
/// 欢迎访问我的博客 http://blog.lindexi.com 从入门到精通
/// </summary>
/// <param name="name">逗比名</param>
/// <param name="text">逗比</param>
static void Main(string name, string text)

此时输入 dotnet run -- --help 就可以看到下面代码

DallairhacelKurbegofa:
欢迎访问我的博客 http://blog.lindexi.com 从入门到精通 Usage:
DallairhacelKurbegofa [options] Options:
--name <NAME> 逗比名
--text <TEXT> 逗比
--version Display version information

那么这个库是如何做黑科技让你的主函数可以修改参数的?

打开System.CommandLine.DragonFruit.targets 就可以看到 GenerateRealEntryPointType 修改启动项目

修改 StartupObject 可以指定调用的主函数是哪个类里的

    <PropertyGroup>
<StartupObject>AutoGeneratedProgram</StartupObject>
</PropertyGroup>

创建动态代码写入到 obj 文件夹里面的 xx.g.cs 文件,写入下面代码

// <auto-generated>This file was created automatically</auto-generated>
using System.CommandLine.DragonFruit;
using System.Runtime.CompilerServices;
using System.Threading.Tasks; [CompilerGenerated]
internal class AutoGeneratedProgram
{
public static async Task<int> Main(string[] args)
{
return await CommandLine.ExecuteAssemblyAsync(
entryAssembly: typeof(global::AutoGeneratedProgram).Assembly,
args: args);
}
}

因为运行的启动函数就是 AutoGeneratedProgram 里面的主函数,所以其实你写的主函数不是主函数

如果想自己也修改主函数,请看Roslyn 通过 NuGet 库修改应用程序入口函数

想知道这个库是如何做的,请看源代码dotnet/command-line-api: System.CommandLine: Command line parsing, invocation, and rendering of terminal output.

最新文章

  1. equals变量在前面或者在后面有什么区别吗?这是一个坑点
  2. bzoj3747
  3. 转几篇WPF文章
  4. 分布式数据库中间件TDDL、Amoeba、Cobar、MyCAT架构比较分
  5. C# Wpf异步修改UI,多线程修改UI(二)
  6. C语言笔记(数组地址一些细节)
  7. 在C#中internal关键字是什么意思?和protected internal区别
  8. gets和从键盘输入换行符
  9. Jsp中out.println()与System.out.println()的区别
  10. 201521123025&lt;java程序设计&gt;第五周学习总结
  11. Android Annotations(2)
  12. BZOJ3174 TJOI2013 拯救小矮人 贪心、DP
  13. Python学习笔记,day5
  14. P1638 逛画展(直尺法)
  15. Web服务API
  16. 关于mongodb基础的命令
  17. lua第三方库
  18. Win7 VS2015环境编译cegui-0.8.5
  19. 解决 Could not resolve com.android.tools.build:gradle:3.1.3
  20. #C++初学记录(算法2)

热门文章

  1. numpy库数组属性查看:类型、尺寸、形状、维度
  2. UVA11107 Life Forms SA模板
  3. springcloud熔断器代码简单实现
  4. Windows 禁用Windows updata服务
  5. 基于RBAC权限管理的后台管理系统
  6. 【arc077f】AtCoder Regular Contest 074 F - Lotus Leaves
  7. Ubuntu linux下部署golang配置环境,极客学院 无闻讲的安装配置是错的,折腾我好几遍,真是有点坑
  8. nslookup查不到数据
  9. CentOS 7 yum 安装与配置MySQL5.7
  10. Linux 中查询 CPU 的核数的方法