将.NET Core 3.1控制台应用程序作为Windows服务

10
我目前有一个使用ASP.NET Core 3.1的大型控制台应用程序。现在我的任务是将其作为Windows服务运行在我们的一台服务器上。我已经准备好让它在服务器上作为服务运行,但是我现在遇到的唯一问题是如何在代码中实际更改它以使其作为服务运行而不破坏它。
我找到了一些像this这样的教程,它们确实解释了如何将控制台应用程序作为服务运行,但是我找到的所有教程都是从零开始的新项目。我的问题是,我的当前项目已经编写完毕。我请求帮助的主要问题是,我该如何使我的项目作为Windows服务工作,并保留当前在startup.cs中的功能。以下是我的当前startup.cs和program.cs供参考:

Startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddSignalR();
        services.AddTransient<SharePointUploader>();
        services.AddTransient<FileUploadService>();
        services.AddSingleton<UploaderHub>();
        //services.AddAuthentication(IISDefaults.AuthenticationScheme);
        services.AddAuthentication(NegotiateDefaults.AuthenticationScheme).AddNegotiate();
        services.AddAuthorization();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseHttpsRedirection();
        }

        app.UseRouting();

        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapHub<UploaderHub>("/uploadHub");
        });
    }
}

Program.cs

public class Program
{
    public static void Main(string[] args)
    {
        var logger = NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
        try
        {
            logger.Debug("init main");
            CreateHostBuilder(args).Build().Run();
        }
        catch (Exception exception)
        {
            //NLog: catch setup errors
            logger.Error(exception, "Stopped program because of exception");
            throw;
        }
        finally
        {
            // Ensure to flush and stop internal timers/threads before application-exit (Avoid segmentation fault on Linux)
            NLog.LogManager.Shutdown();
        }
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.SetMinimumLevel(LogLevel.Trace);
            })
            .UseNLog();
}

我真的不太明白如果作为 Windows 服务运行时它应该如何工作(基于上面链接的教程)。非常感谢任何帮助。

1
你有没有阅读官方文档,网址为https://learn.microsoft.com/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-3.1? - Sir Rufo
3个回答

7

我忘记回答这个问题,因为几小时后我解决了它,但是你只需要在 Host.CreateDefaultBuilder(args) 行中添加 ".UseWindowsService()"。

例如:

 public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()                     //<==== THIS LINE
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            })
            .ConfigureLogging(logging =>
            {
                logging.ClearProviders();
                logging.SetMinimumLevel(LogLevel.Trace);
            })
            .UseNLog();

5
UseWindowsService是NuGet包Microsoft.Extensions.Hosting.WindowsServices中的一个功能。 - pr0gg3r
我有一个控制台应用程序,将调用WCF服务,并需要传递证书。我已经传递了证书,但是出现了SSL/TLS关系信任错误。相同的代码在.NET 4.5框架下工作正常,但在.NET Core 5.0框架下会出现SSL异常。请问如何在.NET Core控制台应用程序中传递证书? - Rohit Vyas

5

使用 IWebHostBuilder 而不是 IHostBuilder:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            // Configure the app here.
        })
        .UseNLog()
        .UseUrls("http://localhost:5001/;" +
                    "https://localhost:5002/;")
        .UseStartup<Startup>();

您还需要安装以下软件包:
Microsoft.AspNetCore.Hosting;
Microsoft.AspNetCore.Hosting.WindowsServices;

修改您的主函数:

bool isService = !(Debugger.IsAttached || args.Contains("--console"));
var builder = CreateWebHostBuilder(args.Where(arg => arg != "--console").ToArray());
var host = builder.Build();

if (isService)
{
    host.RunAsService();
}
else
{
    host.Run();
}

使用工具sc.exe安装服务。通过将--console作为参数传递给应用程序,可以将应用程序运行为控制台应用程序。调试时也需要传递--console。


1
在我的情况下,我已经在主机构建器设置中包含了一个“UseWindowsService()”语句。然而,我将该配置分散到多个行中,并且问题是,在开发过程中的某个时刻,我还放置了一个:ALSO语句混合在代码中。一旦我弄清楚了发生了什么,使用以下部分代码块解决了这个问题:
        var hostBuilder = Host.CreateDefaultBuilder(args);
        if (WindowsServiceHelpers.IsWindowsService())
        {
            hostBuilder.UseWindowsService();
        }
        else
        {
            hostBuilder.UseConsoleLifetime();
        }

注意,WindowsServiceHelpers是位于"Microsoft.Extensions.Hosting.WindowsServices"命名空间中的静态类。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接