Mar*_*ter 4 .net c# windows service asp.net-core
最近,我需要将.Net Core 3.0控制台应用程序转换为Windows服务。
由于我不需要将此过程移植到Linux,因此我可以省去我在Stackoverflow上看到的涉及.Net Framework,.Net Standard和.Net Core任意组合的多平台解决方案。
编辑:Visual Studio 2019即将推出一个工作程序模板。由于它是预发布版本,因此会存在一些潜在的稳定性问题。我无法使用其中的一种参考,因此在模板稳定之前,我在下面提出的解决方案就足够了。(请参阅https://devblogs.microsoft.com/aspnet/net-core-workers-as-windows-services/)
现在转到Program.cs并复制以下内容:
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace AdvancedHost
{
internal class Program
{
private static async Task Main(string[] args)
{
var isService = !(Debugger.IsAttached || args.Contains("--console"));
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<LoggingService>();
});
if (isService)
{
await builder.RunAsServiceAsync();
}
else
{
await builder.RunConsoleAsync();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
该代码将支持交互式调试和生产执行,并运行示例类LoggingService。
这是服务本身的骨架示例:
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using System;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace AdvancedHost
{
public class LoggingService : IHostedService, IDisposable
{
public Task StartAsync(CancellationToken cancellationToken)
{
// Startup code
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
// Stop timers, services
return Task.CompletedTask;
}
public void Dispose()
{
// dispose of non-managed resources
}
}
}
Run Code Online (Sandbox Code Playgroud)
完成项目所需的最后两个文件:
ServiceBaseLifetime.cs:
using Microsoft.Extensions.Hosting;
using System;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
namespace AdvancedHost
{
public class ServiceBaseLifetime : ServiceBase, IHostLifetime
{
private readonly TaskCompletionSource<object> _delayStart = new TaskCompletionSource<object>();
public ServiceBaseLifetime(IApplicationLifetime applicationLifetime)
{
ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime));
}
private IApplicationLifetime ApplicationLifetime { get; }
public Task WaitForStartAsync(CancellationToken cancellationToken)
{
cancellationToken.Register(() => _delayStart.TrySetCanceled());
ApplicationLifetime.ApplicationStopping.Register(Stop);
new Thread(Run).Start(); // Otherwise this would block and prevent IHost.StartAsync from finishing.
return _delayStart.Task;
}
private void Run()
{
try
{
Run(this); // This blocks until the service is stopped.
_delayStart.TrySetException(new InvalidOperationException("Stopped without starting"));
}
catch (Exception ex)
{
_delayStart.TrySetException(ex);
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
Stop();
return Task.CompletedTask;
}
// Called by base.Run when the service is ready to start.
protected override void OnStart(string[] args)
{
_delayStart.TrySetResult(null);
base.OnStart(args);
}
// Called by base.Stop. This may be called multiple times by service Stop, ApplicationStopping, and StopAsync.
// That's OK because StopApplication uses a CancellationTokenSource and prevents any recursion.
protected override void OnStop()
{
ApplicationLifetime.StopApplication();
base.OnStop();
}
}
}
Run Code Online (Sandbox Code Playgroud)
ServiceBaseLifetimeHostExtensions.cs:
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace AdvancedHost
{
public static class ServiceBaseLifetimeHostExtensions
{
public static IHostBuilder UseServiceBaseLifetime(this IHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices((hostContext, services) => services.AddSingleton<IHostLifetime, ServiceBaseLifetime>());
}
public static Task RunAsServiceAsync(this IHostBuilder hostBuilder, CancellationToken cancellationToken = default)
{
return hostBuilder.UseServiceBaseLifetime().Build().RunAsync(cancellationToken);
}
}
}
Run Code Online (Sandbox Code Playgroud)
为了维护该服务,我使用了'sc'实用程序:创建:sc创建AdvancedHost binPath =“ C:\ temp \ AdvancedHost \ AdvancedHost.exe”,其中“ AdvancedHost”是服务名称,binPath的值是已编译的可执行文件。
状态:sc查询AdvancedHost
要启动:sc启动AdvancedHost
停止:sc停止AdvancedHost
删除(一旦停止):sc删除AdvancedHost
sc中包含更多功能。只需在命令行上单独输入“ sc”即可。sc的结果可以在服务Windows控制面板中看到。
| 归档时间: |
|
| 查看次数: |
2908 次 |
| 最近记录: |