此文源于前公司在迁移项目到.NET Core的过程中,希望使用Generic Host来管理定时任务程序时,没法部署到Windows服务的问题,而且官方也没给出解决方案,只能关注一下官方issue #809 等他们方解决了。

官方文档只提供了一个《在 Windows 服务中托管 ASP.NET Core》的方案,可以使用Microsoft.AspNetCore.Hosting.WindowsServices类库来把Web应用部署为Windows服务。但是ASP.NET Core虽然是控制台程序,但是它本身是使用了含有HTTP管道的Web Host来负责应用程序的生命周期管理,用它来作为定时任务的话,会有很多不必要的工作负载,例如占用端口、增加了很多依赖等等。

官方意识到这个问题之后,在.NET Core 2.1版本新增了Generic Host通用主机,剥离了原来WebHost的Http管道相关的API,源码中可以发现Web Host已经基于Generic Host实现。它才是作为纯粹定时任务程序的最佳拍档。

但是由于Generic Host本身非常简单,用它运行的程序设置在注册为Windows服务启动之后会自动停止。研究很久之后才知道,想在Windows上启动服务,还是不能像Linux上那么简单——

于是尝试结合Topshelf来创建Windows服务,最终成功了。

1|1实现方法

  1. 先实现IHostLifetime接口来接管应用程序的生命周期,其实就是用空的实现来替换掉默认的ConsoleLifetime,这样就可以在之后由Topshelf框架内部去管理生命周期。
    internal class TopshelfLifetime : IHostLifetime
{
public TopshelfLifetime(IApplicationLifetime applicationLifetime, IServiceProvider services)
{
ApplicationLifetime = applicationLifetime ?? throw new ArgumentNullException(nameof(applicationLifetime));
} private IApplicationLifetime ApplicationLifetime { get; } public Task WaitForStartAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
} public Task StopAsync(CancellationToken cancellationToken)
{
return Task.CompletedTask;
}
}
  1. 然后实现IHostedService接口,把后台任务逻辑写到StartAsync方法中,参见官方文档《在 ASP.NET Core 中使用托管服务实现后台任务》,本文示例使用定时写入文本到一个文件来测试定时任务是否成功运行。
    internal class FileWriterService : IHostedService, IDisposable
{
private static string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"test.txt"); private Timer _timer; public Task StartAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested) return Task.FromCanceled(cancellationToken); _timer = new Timer(
(e) => WriteTimeToFile(),
null,
TimeSpan.Zero,
TimeSpan.FromSeconds(10)); return Task.CompletedTask;
} public void WriteTimeToFile()
{
if (!File.Exists(path))
{
using (var sw = File.CreateText(path))
{
sw.WriteLine(DateTime.Now);
}
}
else
{
using (var sw = File.AppendText(path))
{
sw.WriteLine(DateTime.Now);
}
}
} public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0); return Task.CompletedTask;
} public void Dispose()
{
_timer?.Dispose();
}
}
  1. 构建Generic Host,在ConfigureServices方法中注册TopshelfLifetime,并且注册一个托管服务FileWriterService,就能完成Generic Host的简单构建,当然完整的项目应该还包含配置、日志等等。最后,使用Topshelf来接管Generic Host,创建Windows服务。
    internal class Program
{
private static void Main(string[] args)
{
var builder = new HostBuilder()
.ConfigureServices((hostContext, services) =>
{
services.AddSingleton<IHostLifetime, TopshelfLifetime>();
services.AddHostedService<FileWriterService>();
}); HostFactory.Run(x =>
{
x.SetServiceName("GenericHostWindowsServiceWithTopshelf");
x.SetDisplayName("Topshelf创建的Generic Host服务");
x.SetDescription("运行Topshelf创建的Generic Host服务"); x.Service<IHost>(s =>
{
s.ConstructUsing(() => builder.Build());
s.WhenStarted(service =>
{
service.Start();
});
s.WhenStopped(service =>
{
service.StopAsync();
});
});
});
}
}
  1. 最后发布应用程序,并安装到Windows服务。

以管理员权限开启终端,执行命令:

  dotnet publish -c release -r win-x64

  cd path-to-project/bin/release/netcoreapp2.1/win-x64/publish

  ./project-name install

  net start GenericHostWindowsServiceWithTopshelf

这样这个Windows服务就启动了!查看输出文件,可以看到定时写入成功,服务也一直没关闭~

1|2示例代码

https://github.com/ElderJames/GenericHostWindowsServiceWithTopshelf

1|3参考链接

官方文档《.NET 通用主机》

官方文档《在 ASP.NET Core 中使用托管服务实现后台任务》

__EOF__

作  者:ElderJames

.NET Core Generic Host Windows服务部署使用Topshelf的更多相关文章

  1. .NET Core Generic Host项目使用Topshelf部署为Windows服务

    1..NET Core Generic Host是什么? 在.NET Core 2.1版本加入了一种新的Host,即Generic Host(通用主机). 现在在2.1版本的Asp.Net Core中 ...

  2. .NET CORE QuartzJob定时任务+Windows/Linux部署

    前言 以前总结过一篇基于Quartz+Topshelf+.netcore实现定时任务Windows服务 https://www.cnblogs.com/gt1987/p/11806053.html.回 ...

  3. 使用.NET Core中创建Windows服务(一) - 使用官方推荐方式

    原文:Creating Windows Services In .NET Core – Part 1 – The "Microsoft" Way 作者:Dotnet Core Tu ...

  4. 利用Topshelf把.NET Core Generic Host管理的应用程序部署为Windows服务

    背景 2019第一篇文章. 此文源于前公司在迁移项目到.NET Core的过程中,希望使用Generic Host来管理定时任务程序时,没法部署到Windows服务的问题,而且官方也没给出解决方案,只 ...

  5. dotnet-warp && NSSM 部署 .net core 项目到 windows 服务

    如果你想将 .net core 项目以服务的形式部署到 windows 系统,希望本篇文章能够让你少走弯路 dotnet-warp 安装使用 dotnet-warp 是一个全局的.NET Core 工 ...

  6. .Net Core快速创建Windows服务

    1.新建.Net Core控制台程序,添加新建项Windows服务: NuGet引用 System.ServiceProcess.ServiceController,然后修改Progran.cs: c ...

  7. asp.net core 托管到windows服务,并用iis做反向代理

    使用NSSM把.Net Core部署至 Windows 服务   为什么部署至Windows Services 在很多情况下,很少会把.Net Core项目部署至Windows服务中,特别是Asp.n ...

  8. windows服务部署与卸载

    同事问到windows service的东东,现在整理一下,用c#如何创建一个windows service,以及如何调试.部署.卸载. 一.创建windows service 1. 打开VS2008 ...

  9. windows服务部署

    1.新建windows服务项目 2.编辑业务代码 我这里只写2句记录文本的测试代码 using System; using System.IO; using System.ServiceProcess ...

随机推荐

  1. (转)C#制作一个消息拦截器

    首先,我们先要制作一个自定义Attribute,让他可以具有上下文读取功能,所以我们这个Attribute类要同时继承Attribute和IContextAttribute. 接口IContextAt ...

  2. Linux后台日志定时清理脚本

    一. 简介 linux是一个很能自动产生文件的系统,日志.邮件.备份等.虽然现在硬盘廉价,我们可以有很多硬盘空间供这些文件浪费,让系统定时清理一些不需要的文件很有一种爽快的事情.不用你去每天惦记着是否 ...

  3. android沉浸状态栏和顶部状态栏背景色的设置

    法一: 现在很多应用都引用了沉浸式状态栏,如QQ,效果下图: 这样的效果很酷炫,其实设置很简单. 不过要说明的是,这种效果只能在API19以及以上版本中才能够做到. 如果想让界面Activity中实现 ...

  4. spring cloud shutdown graceful 优雅停机

    spring cloud shutdown graceful 优雅停机 当一个服务启动后,会注册到eureka中,其他的服务也可以从eureka获取到新注册的服务.但当我们要停止一个服务的时候,如果直 ...

  5. Java-Runtime 类

    https://www.cnblogs.com/slyfox/p/7272048.html Java-Runtime 类 Runtime 类代表着Java程序的运行时环境,每个Java程序都有一个Ru ...

  6. photoshop cc 智能切图

    这节分享一个photoshop cc 开始有的自动生成图标的方法 psd练习文件 http://pan.baidu.com/s/1pL2dwL1 1 工具:我这里用的是photoshop cc 201 ...

  7. HDU 3279 二分图最大匹配

    DES: 就是说对每个人都给你一个区间.但一个人只匹配一个数.问你满足匹配的人的序号字典序最大时的最大匹配是什么. 前几天刚做的UVALive 6322...当然是不一样的...那个要求的最大匹配的个 ...

  8. javascript开发HTML5游戏--斗地主(单机模式part1)

      最近学习使用了一款HTML5游戏引擎(青瓷引擎),并用它尝试做了一个斗地主的游戏,简单实现了单机对战和网络对战,代码可已放到github上,在此谈谈自己如何通过引擎来开发这款游戏的. 客户端代码 ...

  9. docker官方windows安装

    https://docs.docker.com/engine/installation/windows/

  10. 《Python》 面向对象三大特性之继承

    一.继承大纲: 继承和抽象(两个概念) 1.单继承: 语法: 父类.基类.超类 子类.派生类 继承与重用:子类可以使用父类中的名字(变量和方法) 继承与派生:子类在父类的基础上又新创建了自己需要的方法 ...