Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# / .NET - System.CommandLine: how to overwrite the handler for --version?

How can we override the behavior of --version in C# with System.Commandline?

The default implementation unfortunately only shows the version of the app itself, which is rarely useful. If support asks for the version, they usually need more than just the app version and we want to show additional information:

  • The app version
  • The active .NET runtime version
  • The versions of the active add-ons
  • ...

Of course, we don't want two different command line options to display the version, because then we would have to repeatedly explain that they should not use the standard --version parameter (because it is useless).

Hence my question:

  • How can we remove the default --version option in System.CommandLine?
  • Or how can we override the handler for --version?

Thanks a lot for any help!
Thomas

like image 364
Tom Avatar asked Feb 20 '26 01:02

Tom


2 Answers

I assume you are using the daily builds from https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-libraries/nuget/v3/index.json as nuget.org hasn't seen a release in ~2 years.

Above feed URL is listed in the repo itself Github dotnet/command-line-api Daily Builds

With 2.0.0-beta4.24528.1 I found e.g. the following works just fine.

static async Task<int> Main(string[] args)
{
    var rootCommand = new CliRootCommand();
    for (int i = 0; i < rootCommand.Options.Count; i++)
    {
        if (rootCommand.Options[i] is VersionOption)
            rootCommand.Options[i].Action = new YourVersionOptionAction();
    }

    CliConfiguration config = new(rootCommand);

    return await config.InvokeAsync(args);
}
public sealed class YourVersionOptionAction : SynchronousCliAction
{
    public override int Invoke(ParseResult parseResult)
    {
        var appVersion = Assembly.GetExecutingAssembly().GetName().Version;
        var runtimeVersion = Environment.Version;

        parseResult.Configuration.Output.WriteLine($"App Version: {appVersion}");
        parseResult.Configuration.Output.WriteLine($".NET Runtime Version: {runtimeVersion}");
        return 0;
    }
}

I could imagine there is a more elegant/idiomatic way but the docs aren't up-2-date with the repo and I couldn't be bothered to look further

like image 131
jitter Avatar answered Feb 22 '26 13:02

jitter


I have found another solution using a Middleware handler:

public class Program {

   static async Task<int> Main(string[] args) {

      var rootCommand2 = new RootCommand("Sample app for System.CommandLine");

      // Create the CommandLineBuilder with and add the Middleware
      var builder = new CommandLineBuilder(rootCommand2)
                    // Set option verb & shortcut
                   .UseVersionOption("--version", "-v")
                   .AddMiddleware(VersionMiddleware_Handler, MiddlewareOrder.ExceptionHandler)
                   .UseDefaults();

      var parser = builder.Build();
      return await parser.InvokeAsync(args);
   }


   /// <summary>
   /// Changes the Handler for -v / --version
   /// </summary>
   /// <param name="context"></param>
   public static void VersionMiddleware_Handler(InvocationContext context) {
      // Search the --version Option in RootCommand
      var versionOption = context.ParseResult.CommandResult.Command.Options
                                 .FirstOrDefault(o => o.Aliases.Contains("--version"));

      if (versionOption != null) {
         // Test, if the commandline token matches an alias
         var isVersionRequested = context.ParseResult.Tokens
                                         .Any
                                             (t => versionOption.Aliases.Contains
                                                 (t.Value, StringComparer.InvariantCultureIgnoreCase));

         if (isVersionRequested) {
            // Changes the output for --version 
            var version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
            Console.WriteLine($"Version: {version}");
            Console.WriteLine("Additional Data :-)");
            Environment.Exit(0);
         }
      }
   }

like image 25
Tom Avatar answered Feb 22 '26 13:02

Tom



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!