使用Microsoft.Extensions.Hosting.WindowsServices时无法启动Windows服务

我尝试遵循建议here使用microsoft.Extensions.Hosting.WindowsServices创建Windows服务。到目前为止,一切正常,我的后台服务的ExecuteAsync被调用,日志显示一切正常。作为控制台应用程序启动该应用程序也可以正常工作,我可以启动它,做我需要做的一切,然后停止它。

但是,我尝试使用以下方法安装Windows服务:

sc create myservice binPath= "\"<path-to-the-exe-file>\" service" start= auto DisplayName= "My Service"

我得到[SC] CreateService SUCCESS。但是,当我尝试手动启动该服务时,它告诉我它没有及时响应。同样,日志很好,没有错误。事件查看器仅告诉我它可能会出错,并且我不知道下一步该怎么做才能找到问题的原因。

这是我用来配置主机的近似代码:

var containerBuilder = new ContainerBuilder();
IContainer container = null; 

var hostBuilder = Host.CreateDefaultBuilder(appArgs);
hostBuilder
    .UseServiceProviderFactory(new CustomAutofacServiceProviderFactory(() => container))
    .ConfigureServices(services =>
    {
        services.AddHostedService<BackgroundWorker>();
        containerBuilder.Populate(services);
        container = containerBuilder.Build();
    })
    .UseWindowsService();

这是我用于后台服务的类。

public class BackgroundWorker : BackgroundService
{
    private readonly IAppContext appContext;
    private CancellationTokenRegistration stopRegistration;

    public BackgroundWorker(ILogger<BackgroundWorker> logger,IAppContext appContext)
    {
        this.Logger = logger;
        this.appContext = appContext;
    }

    public ILogger<BackgroundWorker> Logger { get; }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        this.Logger.Info("Background worker started.");

        this.stopRegistration = stoppingToken.Register(() =>
        {
            this.Logger.Info("Background worker stopping...");
            this.stopRegistration.Dispose();
            this.Logger.Info("Background worker stopped.");
        });

        return Task.CompletedTask;
    }
}
k702059455 回答:使用Microsoft.Extensions.Hosting.WindowsServices时无法启动Windows服务

经过几个小时的努力,我才找到答案。

我将Autofac用作依赖项注入容器,并且在HostBuilder.ConfigureServices()中,我正在构建Autofac容器。

在我叫.UseWindowsService()之后,已经太晚了,因为Autofac已经完成了构建容器的工作。

因此,答案是,在构建容器之前使用.UseWindowsService(),否则对组合的服务没有影响。

以下是更改后的有效代码:

var containerBuilder = new ContainerBuilder();
IContainer container = null; 

var hostBuilder = Host.CreateDefaultBuilder(appArgs);
hostBuilder
    .UseServiceProviderFactory(new CustomAutofacServiceProviderFactory(() => container))
    .ConfigureServices(services =>
    {
        services.AddHostedService<BackgroundWorker>();
    })
    .UseWindowsService() //<-- Done BEFORE building container
    .ConfigureServices(services =>
    {
        containerBuilder.Populate(services);
        container = containerBuilder.Build();
    })
,

理想情况下,容器不应位于其余设置的外部。

您已经在使用自定义服务提供商工厂,该工厂应包含您的手动操作。

Autofac已经有AutofacServiceProviderFactory

/// <summary>
/// A factory for creating a <see cref="ContainerBuilder"/> and an <see cref="IServiceProvider" />.
/// </summary>
public class AutofacServiceProviderFactory : IServiceProviderFactory<ContainerBuilder>
{
    private readonly Action<ContainerBuilder> _configurationAction;

    /// <summary>
    /// Initializes a new instance of the <see cref="AutofacServiceProviderFactory"/> class.
    /// </summary>
    /// <param name="configurationAction">Action on a <see cref="ContainerBuilder"/> that adds component registrations to the conatiner.</param>
    public AutofacServiceProviderFactory(Action<ContainerBuilder> configurationAction = null)
    {
        _configurationAction = configurationAction ?? (builder => { });
    }

    /// <summary>
    /// Creates a container builder from an <see cref="IServiceCollection" />.
    /// </summary>
    /// <param name="services">The collection of services.</param>
    /// <returns>A container builder that can be used to create an <see cref="IServiceProvider" />.</returns>
    public ContainerBuilder CreateBuilder(IServiceCollection services)
    {
        var builder = new ContainerBuilder();

        builder.Populate(services);

        _configurationAction(builder);

        return builder;
    }

    /// <summary>
    /// Creates an <see cref="IServiceProvider" /> from the container builder.
    /// </summary>
    /// <param name="containerBuilder">The container builder.</param>
    /// <returns>An <see cref="IServiceProvider" />.</returns>
    public IServiceProvider CreateServiceProvider(ContainerBuilder containerBuilder)
    {
        if (containerBuilder == null) throw new ArgumentNullException(nameof(containerBuilder));

        var container = containerBuilder.Build();

        return new AutofacServiceProvider(container);
    }
}

请注意工厂是如何创建和填充容器构建器的,以及如何从IContainer构建服务提供者

这应该允许完成原始设置,而无需在外部手动创建容器

var hostBuilder = Host.CreateDefaultBuilder(appArgs)
    .UseServiceProviderFactory(new AutofacServiceProviderFactory())
    .ConfigureServices(services => {
        services.AddHostedService<BackgroundWorker>();            
    });

引用Documentation

引用NuGet

本文链接:https://www.f2er.com/3144166.html

大家都在问