I am working on a POC for a console application and I am struggling to retrieve the command line values from the configuration after using AddCommandLine in the set up.
csproj
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
Program class
public static class Program
{
public static async Task Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
.Enrich.FromLogContext()
.WriteTo.Console()
.WriteTo.RollingFile("Logs//log.txt")
.CreateLogger();
await CreateHostBuilder(args)
.Build()
.RunAsync();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseSerilog()
.ConfigureAppConfiguration((hostingContext, config) =>
{
config.AddJsonFile("settings.json", true, true);
config.AddCommandLine(args);
})
.ConfigureServices((hostcontext, services) =>
{
services.AddHostedService<ConsoleApp>();
});
}
ConsoleApp class
public class ConsoleApp : IHostedService
{
private readonly IConfiguration config;
private readonly ILogger<ConsoleApp> log;
public ConsoleApp(IConfiguration configuration, ILogger<ConsoleApp> logger)
{
config = configuration;
log = logger;
}
public Task StartAsync(CancellationToken cancellationToken)
{
var t = config.GetSection("Args");
Parser.Default.ParseArguments<DeleteOptions>(t)
.WithParsed<DeleteOptions>()
.WithNotParsed();
foreach (var c in config.AsEnumerable())
{
log.LogInformation($"{c.Key, -15}:{c.Value}");
}
log.LogInformation($"Completing Start Task");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
log.LogInformation($"Complete End Task");
return Task.CompletedTask;
}
}
The Parser section before the foreach loop does not compile and the output from the loop does not print out any of the arguments I have added.
I am aware of the general advice that var someValue = Configuration.GetValue<int>("MySetting:SomeValue");
where the argument is --MySetting=SomeValue
is the recommended way to retrieve cmd line values.
The values I am using as parameters are delete -e CI -t depchpolestar -l de-DE
and when I look at my config object I see
which is why I think the line var t = config.GetSection("Args");
should retrieve the args array. I have also tried var t = config.GetValue<string[]>("Args");
but neither seems to work. It appears to me that index 4 of the configuration object is a string array keyed by "Args"
How do I retrieve the string array so I can pass it into CommandLineParser's ParseArguments method?
[Edit] One Solution:
I can now get the args passed through but it is not a particularly nice approach; If I construct the argument as --delete "-e CI -t depchpolestar -l de-DE"
instead of delete -e CI -t depchpolestar -l de-DE
and adding the following code to the ConsoleApp class:
var args = config.GetValue<string>("delete");
string[] arguments = null;
if(!string.IsNullOrEmpty(args))
{
var tempArgs = args.Split(" ");
arguments = new string[tempArgs.Length + 1];
arguments[0] = "delete";
for(int i = 0; i < tempArgs.Length; ++i)
{
arguments[i + 1] = tempArgs[i];
}
}
Parser.Default.ParseArguments<DeleteOptions>(arguments)
.WithParsed<DeleteOptions>(async c => await c.Dowork())
.WithNotParsed(HandleParseError);
execution hits the DoWork method. Good but DeleteOptions.cs defines a Verb and the intention is to add more commands. So more work to do but going the right way.
[Edit] I have also realised that I do not need to add the AddCommandLine()
call as they are added by default.