Laden...

[erledigt] Worker Service: Abrufen von Konfigurationsparametern

Erstellt von pollito vor 2 Jahren Letzter Beitrag vor 2 Jahren 511 Views
pollito Themenstarter:in
314 Beiträge seit 2010
vor 2 Jahren
[erledigt] Worker Service: Abrufen von Konfigurationsparametern

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é

2.078 Beiträge seit 2012
vor 2 Jahren

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.

Configuration in ASP.NET Core

pollito Themenstarter:in
314 Beiträge seit 2010
vor 2 Jahren

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é

6.911 Beiträge seit 2009
vor 2 Jahren

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!"

6.911 Beiträge seit 2009
vor 2 Jahren

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!"

pollito Themenstarter:in
314 Beiträge seit 2010
vor 2 Jahren

@gfoidl
Vielen Dank! Du und Palladin007 haben mir weitergeholfen.
Wie kann ich den Thread als gelöst kennzeichnen?
LG

René

6.911 Beiträge seit 2009
vor 2 Jahren

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!"