踩坑 Windows 服务来宿主 .NET 程序
本文所指的 .NET 程序为 .NET6 的程序。因为 .NET 的版本更新很快,所以方式、方法也有变化,所以网上搜到的方法有些也过时了。以下是最近我实践下来的一点心得(坑)。
上一篇说到 不安装运行时运行 .NET 程序 后我们的程序已经只有一个 dll/exe 了,但是在 windows 上运行的时候会是一个控制台程序,很容易人不小心关闭了。所以想着把我们的程序部署成 windows 服务,这样不会误关,重启服务器的时候也会自动启动。所以最近折腾了一下把 .NET 程序,特别是 ASP.NET Core 程序部署为 windows 服务。本来以为网上随便搜一搜就很容易,事实上没想得这么美好。
Worker Service
如果你的服务只想执行一些后台任务,比如定时任务,并不提供网站的服务。那么使用 Worker service 项目模板新建一个项目是最合适的。

新建完项目后使用 nuget 安装:
Microsoft.Extensions.Hosting.WindowsServices
修改 program.cs 文件
using WorkerService1;
IHost host = Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
其中就只添加一句 UseWindowsService 就可以了。
编译之后使用 sc 命令就可以注册为服务了。
sc create "wsTest" binPath=wsTest.exe
sc start "wsTest"
pause
我们把它写成一个 bat 文件方便执行。使用管理权限运行这个 bat 文件服务会被注册并且直接运行:

ASP.NET Core
以上尝试了一下 worker service 模式注册为服务,感觉简单的很。但是下面把 ASP.NET Core 程序注册为服务的时候就没那么简单啦。我查了一些文章,写的时间有些早了,所以还是安照微软官方的文档 Host ASP.NET Core in a Windows Service 的提示来操作。这篇文章虽然叫 Host ASP.NET Core in a Windows Service ,但其实里面的内容说的是上面的 worker service 。当按照上面的步骤尝试把 asp.net core 程序部署为服务的时候死活起不来,一直报未找到文件的异常。
我们新建一个最简单的 asp.net core 程序来演示一下:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Host.UseWindowsService();
var app = builder.Build();
app.UseStaticFiles();
app.UseRouting();
await app.RunAsync();
这是一个最简单的 asp.net core razor pages 程序。我们按照文档安装扩展包:
Microsoft.Extensions.Hosting.WindowsServices
然后调用 UseWindowsService 方法
builder.Host.UseWindowsService();
同样使用 sc 命令注册为服务并运行它。很遗憾它会报错。

经过多种尝试方法都不行。最后翻了一下微软仓库里的 sample 代码才发现原来他们自己的 sample 代码里多了几行代码 。
注意下面的代码了啊 !!!
在构建 builder 的时候需要多传几个参数:
var options = new WebApplicationOptions
{
Args = args,
ContentRootPath = WindowsServiceHelpers.IsWindowsService() ? AppContext.BaseDirectory : default
};
var builder = WebApplication.CreateBuilder(options);
只要使用这段代码来构建 builder ,服务就可以顺利的运行起来。根据以往的经验,可能还是作为服务运行的时候程序根目录的问题,通过以上方法来指定 AppContext.BaseDirectory 来作为程序的根目录,不然就有可能被定位到 system32 目录下。
吐槽。。。虽然解决方案很简单,但是微软没有在文档里把这么关键的代码给些出来,着实有点坑啊,辛亏现在代码都在 github 上,很容易翻到,不然得折腾死人。
关注我的公众号一起玩转技术

踩坑 Windows 服务来宿主 .NET 程序的更多相关文章
- Windows 服务为宿主的WCF服务,详细图解。
废话不多说,直接进入主题: 1.打开vs2010新建项目,选择Windows服务. 2.选中WindowsService右击,添加WCF服务. 3.添加成功后,为下图.将接口类ITestService ...
- windows服务启动有界面的程序
大家写windows服务守护进程的时候,肯定会遇到启动的程序看不到界面,只能在任务管理器里面看到xxx.exe问题. 发现可能有如下情况 a.无论是开机,还是程序被关掉后,守护服务启动的程序只能看到任 ...
- Windows服务项目打包成安装包(Windows服务)-----------VS2017项目程序打包成.msi或者.exe
VS2017项目程序打包成.msi或者.exe Windows服务项目使用VS2017项目程序打包成.msi或者.exe安装包 项目打包成安装包(Windows服务) 1.安装打包插件:Microso ...
- C#穿透session隔离———Windows服务启动UI交互程序
在Windows服务里面启动其他具有界面的应用程序,需要穿透session隔离,尝试了很多种方法,都可行,现在一一列举下来,并写下几个需要注意的地方. 需要注意的地方 首先要将服务的Account属性 ...
- C# windows服务,解决应用程序开机自启问题
最近在东营做一个超市购物的项目,业务体量很小,是仅供内部员工使用的内网应用程序,其中涉及一个商品数据同步的winform应用程序,有一个问题就是服务器重启后,必须登录服务器操作系统,手动启动才行,于是 ...
- windows服务怎么向应用程序发消息(部署在同一台机,非SCOKET)
命名管道:NamedPipeClientStream & NamedPipeClientStream 参考实例:http://msdn.microsoft.com/zh-cn/library/ ...
- 将springboot打包成的jar文件做成windows服务,解决java程序自启动问题
https://blog.csdn.net/weixin_40411331/article/details/80193376 https://blog.csdn.net/qq_33188180/art ...
- 踩坑 Windows 解决pip install出现“由于目标计算机积极拒绝,无法连接”的问题
解决pip install出现“由于目标计算机积极拒绝,无法连接”的问题 可能是使用某软件自动设置了代理, 所以需要手动的取消代理才可以. 在Intel选项中把所有的代理都给去掉就可以了... ...
- C#判断程序是由Windows服务启动还是用户启动
在Windows系统做网络开发,很多时候都是使用Windows服务的模式,但在调度阶段,我们更多的是使用控制台的模式.在开发程序的时候,我们在Program的Main入口进行判断.最初开始使用Envi ...
随机推荐
- 强化学习-linux安装gym、atari和box2d环境
安装gym和atari环境 pip3 install gym pip3 install gym[atari] pip3 install gym[accept-rom-license] 安装box2d环 ...
- ABP框架之——数据访问基础架构(下)
大家好,我是张飞洪,感谢您的阅读,我会不定期和你分享学习心得,希望我的文章能成为你成长路上的一块垫脚石,我们一起精进. EF Core集成 EF Core是微软的ORM,可以使用它与主流的数据库提供商 ...
- 又拍云 Redis 的改进之路
作为推出国内首创可编程 CDN 服务的专业云服务提供商,又拍云利用 CDN 边缘网络规模和性能,允许客户自定义编写规则来满足常用业务场景.而为了保证这些源数据,如边缘重定向.请求限速.自定义错误页面. ...
- Python调用Outlook发邮件
调用Outlook发送邮件 需安装pypiwin32模块:pip install pypiwin32 1. 发送普通邮件 import win32com.client as win32 outlook ...
- 记一次重复造轮子(Obsidian 插件设置说明汉化)
杂谈 #Java脚本 因本人英语不好在使用Obsidian时,一些插件的设置英文多令人头痛.故有写一个的翻译插件介绍和设置脚本的想法.看到有些前人写的一下翻译方法,简直惨目忍睹.竟然要手动.这个应该写 ...
- Codeforces Round #802 (Div. 2)
题集链接 A Optimal Path 水 代码 #include <bits/stdc++.h> #define endl "\n" using namespace ...
- Training a classifier
你已经学习了如何定义神经网络,计算损失和执行网络权重的更新. 现在你或许在思考. What about data? 通常当你需要处理图像,文本,音频,视频数据,你能够使用标准的python包将数据加载 ...
- 【Python爬虫技巧】快速格式化请求头Request Headers
你好,我是 @马哥python说 . 我们在写爬虫时,经常遇到这种问题,从目标网站把请求头复制下来,粘贴到爬虫代码里,需要一点一点修改格式,因为复制的是字符串string格式,请求头需要用字典dict ...
- noi-2.2基本算法之递归和自调用函数:放苹果
先看一下题目: http://noi.openjudge.cn/ch0202/666/http://noi.openjudge.cn/ch0202/666/ 把M个同样的苹果放在N个同样的盘子里,允许 ...
- angular 变化检测和ngZone