Windows 服务项目模板在哪
Visual Studio 2019 及之后版本默认**已移除**
Windows Service项目模板。不是你没找到,是它真没了。若用较新版本新建项目,
Windows Forms App或
Console App都不能直接当服务跑——它们缺少服务生命周期管理入口。
正确路径是:新建项目 → 搜索 “
Worker Service” → 选中 .NET 6+ 的模板。这是微软当前推荐的 Windows 服务实现方式,底层基于
IHostedService,比老式
ServiceBase更轻量、更可控。 老式
ServiceBase仍可用,但需手动添加
System.ServiceProcess.ServiceControllerNuGet 包(.NET Core/.NET 5+)
Worker Service模板生成的是跨平台主机,但部署到 Windows 并注册为服务时,行为完全等同传统 Windows 服务 不要试图在 WinForms 或 WPF 项目里“加个服务类”就完事——GUI 线程模型和服务 SCM(Service Control Manager)不兼容,启动必失败
如何把 Worker Service 注册为系统服务
核心命令是
sc.exe,必须以管理员权限运行。注册前确保已发布为自包含(self-contained)或框架依赖(framework-dependent)可执行文件。
假设发布后路径为
C:MyServiceMyService.exe,执行:
sc create "MyServiceName" binPath= "C:MyServiceMyService.exe" start= auto obj= "LocalSystem"
注意:
binPath=后面**必须有空格**,且路径含空格时要加英文双引号;
obj=指定运行账户,
LocalSystem权限高但风险大,生产环境建议用专用服务账户。 启动服务:
sc start "MyServiceName"查看状态:
sc query "MyServiceName"(返回
STATE: 4 RUNNING才算成功) 卸载服务:
sc delete "MyServiceName"(删除前先
sc stop) 日志输出默认写入 Windows 事件查看器 → “Windows 日志 → 应用程序”,不是控制台
为什么服务启动后立即退出
最常见原因是
Program.cs中的主机未被阻塞,进程自然结束。Worker Service 默认使用
Host.CreateDefaultBuilder(),但若你删了
.Run()或替换成
.Start()就会出问题。
正确结构必须包含:
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<MyBackgroundService>();
})
.Build();
<p>host.Run(); // ← 这行不能少,也不能换成 Start()
host.Start()是异步启动,不阻塞主线程,进程立刻退出
host.Run()内部调用
StartAsync()+ 阻塞等待 Ctrl+C 或服务停止信号 若需调试,可在
Main方法末尾加
Console.ReadLine()(仅开发时),但正式部署必须用
Run()检查
MyBackgroundService的
ExecuteAsync(CancellationToken)是否抛异常——未捕获异常会导致服务崩溃并被 SCM 标记为“已停止”
如何让服务能访问网络或文件系统
Windows 服务默认以
LocalSystem账户运行,对本地资源权限足够,但对网络路径(如
\servershare)、映射驱动器、交互式桌面(UI)、用户配置文件(
%USERPROFILE%)均无访问权。 访问 UNC 路径:改用域名账户(
DOMAINsvcuser),并在目标服务器上授予权限;或改用
\ipshare并启用 SMB 签名兼容模式 读写用户目录:不要硬编码
%USERPROFILE%,改用
Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)需要弹窗或操作桌面?别这么做。Windows 服务设计上禁止交互;如真需 GUI,请改用启动类型为
Interactive的旧式服务(不推荐,Win10/11 已限制) 调试时看到“拒绝访问”错误,先查事件查看器里的详细异常堆栈,再确认服务账户权限,而不是盲目加
RequireAdministrator
服务注册和调试的坑集中在权限、路径、生命周期三处。哪怕代码逻辑完全正确,
sc create少个空格、
host.Run()写成
Start()、服务账户没权限访问目标文件夹,都会导致“安装成功但无法启动”。
