web-dev-qa-db-fra.com

Net Core 2.1 Generic Host en tant que service

J'essaie de créer un service Windows en utilisant le dernier runtime Dotnet Core 2.1. Je n'héberge pas d'aspnet, je ne veux pas ou n'ai pas besoin de lui pour répondre aux requêtes http. 

J'ai suivi le code trouvé ici dans les exemples: https://github.com/aspnet/Docs/tree/master/aspnetcore/fundamentals/Host/generic-Host/samples/2.x/GenericHostSample

J'ai aussi lu cet article: https://docs.Microsoft.com/en-us/aspnet/core/fundamentals/Host/generic-host?view=aspnetcore-2.1

Le code fonctionne très bien lorsqu'il est exécuté à l'intérieur d'une fenêtre de console à l'aide de l'exécution de dotnet. J'en ai besoin pour fonctionner en tant que service Windows. Je sais qu'il existe Microsoft.AspNetCore.Hosting.WindowsServices, mais cela concerne WebHost et non l'hôte générique. Nous utiliserions Host.RunAsService () pour fonctionner en tant que service, mais je ne vois pas cela existant nulle part.

Comment est-ce que je configure ceci pour fonctionner en tant que service?

using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace MyNamespace
{
    public class Program
    {


        public static async Task Main(string[] args)
        {
            try
            {
                var Host = new HostBuilder()
                    .ConfigureHostConfiguration(configHost =>
                    {
                        configHost.SetBasePath(Directory.GetCurrentDirectory());
                        configHost.AddJsonFile("hostsettings.json", optional: true);
                        configHost.AddEnvironmentVariables(prefix: "ASPNETCORE_");
                        configHost.AddCommandLine(args);
                    })
                    .ConfigureAppConfiguration((hostContext, configApp) =>
                    {
                        configApp.AddJsonFile("appsettings.json", optional: true);
                        configApp.AddJsonFile(
                            $"appsettings.{hostContext.HostingEnvironment.EnvironmentName}.json",
                            optional: true);
                        configApp.AddEnvironmentVariables(prefix: "ASPNETCORE_");
                        configApp.AddCommandLine(args);
                    })
                    .ConfigureServices((hostContext, services) =>
                    {
                        services.AddLogging();
                        services.AddHostedService<TimedHostedService>();
                    })
                    .ConfigureLogging((hostContext, configLogging) =>
                    {
                        configLogging.AddConsole();
                        configLogging.AddDebug();

                    })

                    .Build();

                await Host.RunAsync();
            }
            catch (Exception ex)
            {



            }
        }


    }

    #region snippet1
    internal class TimedHostedService : IHostedService, IDisposable
    {
        private readonly ILogger _logger;
        private Timer _timer;

        public TimedHostedService(ILogger<TimedHostedService> logger)
        {
            _logger = logger;
        }

        public Task StartAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Timed Background Service is starting.");

            _timer = new Timer(DoWork, null, TimeSpan.Zero,
                TimeSpan.FromSeconds(5));

            return Task.CompletedTask;
        }

        private void DoWork(object state)
        {
            _logger.LogInformation("Timed Background Service is working.");
        }

        public Task StopAsync(CancellationToken cancellationToken)
        {
            _logger.LogInformation("Timed Background Service is stopping.");

            _timer?.Change(Timeout.Infinite, 0);

            return Task.CompletedTask;
        }

        public void Dispose()
        {
            _timer?.Dispose();
        }
    }
    #endregion
}

EDIT: Je répète, il ne s'agit pas d'héberger une application ASP.NET Core. Ceci est un constructeur d'hôte générique, pas un WebHostBuilder.

5
Darthg8r

Comme d'autres l'ont déjà dit, vous devez simplement réutiliser le code qui existe pour l'interface IWebHost. En voici un exemple. 

public class GenericServiceHost : ServiceBase
{
    private IHost _Host;
    private bool _stopRequestedByWindows;

    public GenericServiceHost(IHost Host)
    {
        _Host = Host ?? throw new ArgumentNullException(nameof(Host));
    }

    protected sealed override void OnStart(string[] args)
    {
        OnStarting(args);

        _Host
            .Services
            .GetRequiredService<IApplicationLifetime>()
            .ApplicationStopped
            .Register(() =>
            {
                if (!_stopRequestedByWindows)
                {
                    Stop();
                }
            });

        _Host.Start();

        OnStarted();
    }

    protected sealed override void OnStop()
    {
        _stopRequestedByWindows = true;
        OnStopping();
        try
        {
            _Host.StopAsync().GetAwaiter().GetResult();
        }
        finally
        {
            _Host.Dispose();
            OnStopped();
        }
    }

    protected virtual void OnStarting(string[] args) { }

    protected virtual void OnStarted() { }

    protected virtual void OnStopping() { }

    protected virtual void OnStopped() { }
}

public static class GenericHostWindowsServiceExtensions
{
    public static void RunAsService(this IHost Host)
    {
        var hostService = new GenericServiceHost(Host);
        ServiceBase.Run(hostService);
    }
}
6
Colin Bull

IHostedService si pour [asp.net core] backendjob, si vous voulez créer un service Windows sur un noyau .net, vous devez référencer ce package System.ServiceProcess.ServiceController , et utiliser ServiceBase comme classe de base . (vous pouvez également démarrer à partir d'un service Windows .net Framework, puis modifier le fichier .csproj)


edit: veuillez consulter cette doc et ce code https://github.com/aspnet/Hosting/blob/dev/src/Microsoft.AspNetCore.Hosting.WindowsServices/WebHostWindowsServiceExtensions.cs . Pour créer un service Windows ServiceBase pour gérer votre IHost

1
John

J'espère que vous avez trouvé la solution à ce problème. 

Dans mon cas, j’ai utilisé un hôte générique (introduit en 2.1) à cette fin, puis je l’enveloppais avec systemd pour l’exécuter en tant que service sur un hôte Linux. 

J'ai écrit un petit article à ce sujet https://dejanstojanovic.net/aspnet/2018/june/clean-service-stop-on-linux-with-net-core-21/

J'espère que ça aide

0
Dejan Stojanović