[英].NET Core 3.1 Console App as a Windows Service
I currently have a pretty big console app running with ASP.NET Core 3.1.我目前有一个运行 ASP.NET Core 3.1 的相当大的控制台应用程序。 I have been tasked with now making this work on one of our servers as a Window Service.
我现在的任务是在我们的一台服务器上将这项工作作为窗口服务进行。 I have everything ready to make it run as a service on the server itself, however, the one thing I am stuck on at the moment is how to actually change it in code to make it run as a service without breaking it.
我已经准备好让它在服务器本身上作为服务运行,但是,我目前遇到的一件事是如何在代码中实际更改它以使其作为服务运行而不会破坏它。
I have found a couple of tutorials like this that do explain how to run a console app as a service, however, all of them that I have found start from a fresh project.我已经发现一对夫妇像教程这是做解释如何运行一个控制台应用程序作为一种服务,但是,所有的人,我已经从一个全新的项目中找到的开始。 My issue is that my current project has already been written.
我的问题是我当前的项目已经写好了。 The main problem that I am asking for help with is how would I go about making my project work as a windows service while also keeping the functionality that is currently in a startup.cs.
我寻求帮助的主要问题是如何让我的项目作为 Windows 服务工作,同时保持当前在 startup.cs 中的功能。 For context, here is my current startup.cs and program.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程序.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();
}
I don't really understand how this is supposed to work when run as a windows service (based on tutorials like linked above).我真的不明白这在作为 Windows 服务运行时应该如何工作(基于上面链接的教程)。 Any help would be greatly appreciated.
任何帮助将不胜感激。
Use IWebHostBuilder instead of IHostBuilder:使用 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>();
You also need the following packages:您还需要以下软件包:
Microsoft.AspNetCore.Hosting;
Microsoft.AspNetCore.Hosting.WindowsServices;
Modify your main function:修改你的主函数:
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();
}
For installation of the service use the tool sc.exe.要安装服务,请使用工具 sc.exe。 You can run the app as console app by passing --console as argument to the app.
您可以通过将 --console 作为参数传递给应用程序来将应用程序作为控制台应用程序运行。 For debugging you need to pass --console as well.
对于调试,您还需要传递 --console 。
I forgot about answering this question as I solved it a few hours later after I asked it, but you can just add ".UseWindowsService()" to the Host.CreateDefaultBuilder(args) line.我忘了回答这个问题,因为我在问它几个小时后解决了这个问题,但你可以将“.UseWindowsService()”添加到 Host.CreateDefaultBuilder(args) 行。 eg:
例如:
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();
In my case, I did have a "UseWindowsService()" statement included in my host builder setup.就我而言,我的主机构建器设置中确实包含了“UseWindowsService()”语句。 However, I have that configuration broken out across multiple lines and the problem was that, at some point during development, I had ALSO placed a:
不过,我有一个配置在多行爆发了,问题是,在开发过程中的某个时刻,我也放在:
UseConsoleLifetime()
UseConsoleLifetime()
statement into the mix further down in the code.语句在代码中进一步混合。 Once I figured out what was going on, using the following partial code block resolved the issue:
一旦我弄清楚发生了什么,使用以下部分代码块解决了这个问题:
var hostBuilder = Host.CreateDefaultBuilder(args);
if (WindowsServiceHelpers.IsWindowsService())
{
hostBuilder.UseWindowsService();
}
else
{
hostBuilder.UseConsoleLifetime();
}
Note, WindowsServiceHelpers is a static class in the "Microsoft.Extensions.Hosting.WindowsServices" namespace.请注意,WindowsServiceHelpers 是“Microsoft.Extensions.Hosting.WindowsServices”命名空间中的静态类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.