【问题标题】:.NET Core 3.1 Console App as a Windows Service.NET Core 3.1 控制台应用程序作为 Windows 服务
【发布时间】:2020-02-27 04:20:00
【问题描述】:

我目前有一个运行 ASP.NET Core 3.1 的大型控制台应用程序。我的任务是现在将这项工作作为窗口服务在我们的一台服务器上工作。我已经准备好让它在服务器本身上作为服务运行,但是,我目前坚持的一件事是如何在代码中实际更改它以使其作为服务运行而不会破坏它。

我找到了一些教程,例如 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 服务运行时应该如何工作(基于上面链接的教程)。任何帮助将不胜感激。

【问题讨论】:

标签: c# windows-services asp.net-core-3.1


【解决方案1】:

我忘了回答这个问题,因为我在问了几个小时后才解决了这个问题,但是您可以将“.UseWindowsService()”添加到 Host.CreateDefaultBuilder(args) 行。 例如:

 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();

【讨论】:

  • UseWindowsService 在 NuGet 包 Microsoft.Extensions.Hosting.WindowsServices 中
  • 我有一个将调用 WCF 服务的控制台应用程序,我需要传递一个证书,我正在传递证书,但出现 SSL/TLS 关系信任错误,相同的代码正在使用 .net 4.5 FW 但使用 .net core FW 5.0 gettin SSL 异常,知道如何在 .net core 控制台应用程序中传递证书吗?
【解决方案2】:

使用 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。

【讨论】:

    【解决方案3】:

    就我而言,我的主机构建器设置中确实包含了“UseWindowsService()”语句。但是,我将该配置拆分为多行,问题是,在开发过程中的某个时刻,我 ALSO 放置了:

    UseConsoleLifetime()

    在代码中进一步混合声明。一旦我弄清楚发生了什么,使用以下部分代码块解决了这个问题:

            var hostBuilder = Host.CreateDefaultBuilder(args);
            if (WindowsServiceHelpers.IsWindowsService())
            {
                hostBuilder.UseWindowsService();
            }
            else
            {
                hostBuilder.UseConsoleLifetime();
            }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-07
      • 1970-01-01
      • 2020-07-09
      • 2020-10-27
      • 1970-01-01
      • 2020-07-14
      • 1970-01-01
      相关资源
      最近更新 更多