Windows服务项目模板在VS 2019+中已被移除,应使用Worker Service模板(.NET 6+),通过sc.exe注册为系统服务,并确保Program.cs中调用host.Run()阻塞主线程。
Visual Studio 2019 及之后版本默认**已移除** Windows Service 项目模板。不是你没找到,是它真没了。若用较新版本新建项目,Windows Forms App 或 Console App 都不能直接当服务跑——它们缺少服

正确路径是:新建项目 → 搜索 “Worker Service” → 选中 .NET 6+ 的模板。这是微软当前推荐的 Windows 服务实现方式,底层基于 IHostedService,比老式 ServiceBase 更轻量、更可控。
ServiceBase 仍可用,但需手动添加 System.ServiceProcess.ServiceController NuGet 包(.NET Core/.NET 5+)Worker Service 模板生成的是跨平台主机,但部署到 Windows 并注册为服务时,行为完全等同传统 Windows 服务核心命令是 sc.exe,必须以管理员权限运行。注册前确保已发布为自包含(self-contained)或框架依赖(framework-dependent)可执行文件。
假设发布后路径为 C:\MyService\MyService.exe,执行:
sc create "MyServiceName" binPath= "C:\MyService\MyService.exe" start= auto obj= "LocalSystem"
注意:binPath= 后面**必须有空格**,且路径含空格时要加英文双引号;obj= 指定运行账户,LocalSystem 权限高但风险大,生产环境建议用专用服务账户。
sc start "MyServiceName"
sc query "MyServiceName"(返回 STATE: 4 RUNNING 才算成功)sc delete "MyServiceName"(删除前先 sc stop)最常见原因是 Program.cs 中的主机未被阻塞,进程自然结束。Worker Service 默认使用 Host.CreateDefaultBuilder(),但若你删了 .Run() 或替换成 .Start() 就会出问题。
正确结构必须包含:
var host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService();
})
.Build();
host.Run(); // ← 这行不能少,也不能换成 Start()
host.Start() 是异步启动,不阻塞主线程,进程立刻退出host.Run() 内部调用 StartAsync() + 阻塞等待 Ctrl+C 或服务停止信号Main 方法末尾加 Console.ReadLine()(仅开发时),但正式部署必须用 Run()
MyBackgroundService 的 ExecuteAsync(CancellationToken) 是否抛异常——未捕获异常会导致服务崩溃并被 SCM 标记为“已停止”Windows 服务默认以 LocalSystem 账户运行,对本地资源权限足够,但对网络路径(如 \\server\share)、映射驱动器、交互式桌面(UI)、用户配置文件(%USERPROFILE%)均无访问权。
DOMAIN\svcuser),并在目标服务器上授予权限;或改用 \\ip\share 并启用 SMB 签名兼容模式%USERPROFILE%,改用 Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)
Interactive 的旧式服务(不推荐,Win10/11 已限制)RequireAdministrator
服务注册和调试的坑集中在权限、路径、生命周期三处。哪怕代码逻辑完全正确,sc create 少个空格、host.Run() 写成 Start()、服务账户没权限访问目标文件夹,都会导致“安装成功但无法启动”。