Hallo,
ich mache meine ersten Schritte mit .Net 6 und versuche einen Dienst mit Hilfe von BackgroundService zu erstellen. Die Grundlagen sind von Microsoft relativ gut beschrieben, aber eine Sache will mir nicht gelingen: Das Abrufen von Parametern im Worker Service.
In meinem Beispiel würde ich gerne die Parameter der Kommandozeile abrufen. Diese stehen auch im Worker in "Configuration" zur Verfügung, ich weiß aber nicht, wie ich den Wert programmtechnisch abrufen muss.
using BackgroundServiceTest;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
namespace BackgroundServiceTest
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> Logger;
public Worker(ILogger<Worker> logger, IConfiguration configuration)
{
Logger = logger;
Configuration = configuration;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}
}
Unten sieht man in [4] die Parameter der Kommandozeile (hier nur ein Stück). Nun komme ich programmtechnisch nicht auf den Wert.
Name Wert
Configuration {Microsoft.Extensions.Configuration.ConfigurationRoot}
◢ Providers Count = 5
▶ [0] {Microsoft.Extensions.Configuration.ChainedConfigurationProvider}
▶ [1] {JsonConfigurationProvider for 'appsettings.json' (Optional)}
▶ [2] {JsonConfigurationProvider for 'appsettings.Development.json' (Optional)}
▶ [3] {EnvironmentVariablesConfigurationProvider Prefix: ''}
◢ [4] {CommandLineConfigurationProvider}
◢ Args {string[1]}
[0] "C:\\Daten\\Visual Studio\\Projects\\Tests\\.Net 6\\WorkerService\\Datei.txt"
▶ Data Count = 0
▶ Nicht öffentliche Member
▶ Rohdatenansicht
▶ Nicht öffentliche Member
Klar kann ich die Kommandozeile anders ermitteln, aber die Frage gilt auch für andere mit
.ConfigureAppConfiguration(app =>
{
...
})
hinzugefügten Parameter.
Es wäre super, wenn jemand mir einen Tipp geben könnte.
Schönen Dank und LG
René
Die Args müssen weiterhin Key-Value-Paare abbilden, einzelne Werte (z.B. nur ein Datei-Pfad) sind nicht möglich.
Den Key kannst Du dann benutzen, um den Wert zu bekommen, so wie man es mit IConfiguration so macht.
Man kann damit z.B. appsettings-Einträge durch die Kommandozeile überschreiben, muss dafür aber auch den passenden Wert verwenden.
NuGet Packages im Code auslesen
lock Alternative für async/await
Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.
Danke, das hat mir weitergeholfen. Wenn ich in der Kommandozeile den Dateinamen als KeyValue angebe wie z. B.
Datei="C:\\Daten\\Visual Studio\\Projects\\Tests\\.Net 6\\WorkerService\\Datei.txt"
bekomme ich
Name Wert
Configuration {Microsoft.Extensions.Configuration.ConfigurationRoot}
◢ Providers Count = 5
▶ [0] {Microsoft.Extensions.Configuration.ChainedConfigurationProvider}
▶ [1] {JsonConfigurationProvider for 'appsettings.json' (Optional)}
▶ [2] {JsonConfigurationProvider for 'appsettings.Development.json' (Optional)}
▶ [3] {EnvironmentVariablesConfigurationProvider Prefix: ''}
◢ [4] {CommandLineConfigurationProvider}
◢ Args {string[1]}
[0] "C:\\Daten\\Visual Studio\\Projects\\Tests\\.Net 6\\WorkerService\\Datei.txt"
◢ Data Count = 1
◢ [0]
Key "Datei"
Value "C:\\Daten\\Visual Studio\\Projects\\Tests\\.Net 6\\WorkerService\\Datei.txt"
▶ Nicht öffentliche Member
▶ Rohdatenansicht
▶ Nicht öffentliche Member
Mit
Configuration["Datei"]
bekomme ich zwar den gewünschten Wert, aber woher weiß C# in welchem der 5 Provider es suchen muss? Kann ich den Provider gezielt angeben?
Nochmals vielen Dank und LG
René
Hallo pollito,
wenn du unbedingt auf die Key-Value-Paare für die Kommandozeilen-Argumente verzichten möchtest, so kann beim Einstieg ins Programm die Befehlszeile geparst werden und ein Objekt erstellt werden, welches dann via DI als Singleton registriert wird. Dies kann im Worker geholt werden.
Ganz grob:
using BackgroundServiceTest;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
CommandLineArgs clArgs = ParseCommandLineArgs(args);
services.AddSingleton(clArgs);
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
Nebenbei gibt es von überall aus auch den Weg via Environment.GetCommandLineArgs()
, aber das würde ich eher als Notlösung sehen.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
Hallo pollito,
aber woher weiß C# in welchem der 5 Provider es suchen muss? Kann ich den Provider gezielt angeben?
C# ist das recht egal, solange das .NET Framework das weiß.
Die Provider bauen aufeinander auf, so dass später hinzugefügt die Werte von vorher hinzugefügten überschreiben können. Das meinte auch Palladin007 mit
Man kann damit z.B. appsettings-Einträge durch die Kommandozeile überschreiben, muss dafür aber auch den passenden Wert verwenden.
Lies dir bitte die Doku nochmal durch, damit du das Verständnis dafür bekommst.
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"
@gfoidl
Vielen Dank! Du und Palladin007 haben mir weitergeholfen.
Wie kann ich den Thread als gelöst kennzeichnen?
LG
René
Hallo pollito,
Wie kann ich den Thread als gelöst kennzeichnen?
Einen richtigen Mechanismus dafür haben wir momentan nicht, aber oftmals wird einfach dem Themen-Titel ein [erledigt]
vorangestellt.
Dazu den Startbeitrag editieren, damit der Titel geändert werden kann.
Edit: sorry, hab vergessen dass das so nicht mehr geht (ging im alten Forum so).
mfG Gü
Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.
"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"