必须选「windows 服务(.net framework)」模板,因其生成service1.cs和projectinstaller.cs,天然适配windows scm及installutil.exe;而「windows 服务(.net)」和「worker service」属.net core/5+,不支持installutil.exe,需sc create或powershell安装。

Visual Studio 2022 创建 Windows 服务项目时选什么模板
必须选「Windows 服务(.NET Framework)」,不是「Windows 服务(.NET)」或「Worker Service」。后者是 .NET Core/.NET 5+ 的跨平台后台服务,不支持 installutil.exe 安装、无法注册为传统 Windows Service,也不能设为 LocalSystem 账户自动启动。
常见错误现象:InstallUtil.exe 报错 System.InvalidOperationException: 找不到服务安装程序,基本就是模板选错了。
- .NET Framework 模板生成的项目含
Service1.cs和ProjectInstaller.cs,天然适配 Windows SCM(服务控制管理器) - .NET 5+ 的
Worker Service模板默认走Microsoft.Extensions.Hosting,需额外封装成 Windows 服务(如用UseWindowsService()),且必须用sc create或 PowerShell 安装,installutil.exe对它完全无效 - 框架版本建议锁定在
.NET Framework 4.7.2或以上——太老(如 4.5.2)可能缺ServiceBase.OnContinue等方法;太新(如 4.8.1)在部分 Server OS 上偶有兼容性抖动
ServiceInstaller 和 ServiceProcessInstaller 的关键属性怎么设
这两个组件由「右键设计视图 → 添加安装程序」自动生成,但默认值几乎都不能直接用。不改就装上也起不来,或者起不来还报错没提示。
-
serviceInstaller.ServiceName:必须和代码中ServiceBase.ServiceName字符串完全一致(区分大小写),否则net start xxx找不到服务。建议统一设为"MyAppBackend"这类无空格纯英文名 -
serviceInstaller.StartType:选Automatic(开机自启)还是Manual(手动启动),别留默认的Manual还以为能自启 -
serviceProcessInstaller.Account:生产环境慎选LocalSystem(权限过大);调试阶段可先用,上线前应改为NetworkService或指定域账户;若服务要访问网络资源,LocalService可能因无网络凭据失败 -
serviceInstaller.Description:虽然不影响运行,但 Windows 服务管理器里显示为空白会增加运维困惑,建议填一句实际用途,如"采集PLC数据并写入本地数据库"
OnStart 里不能直接阻塞,那长时间任务怎么放
OnStart 方法必须快速返回,Windows SCM 会在 30 秒内检查服务是否“已启动”。如果在里面写 while(true) 或同步连接数据库/PLC,服务状态卡在 “Starting” 直到超时,然后被系统标记为失败。
- 正确做法:在
OnStart中启动一个后台线程或Task,把主逻辑放进去;同时设个private volatile bool _isRunning = true;控制生命周期 - 别用
Thread.Sleep做轮询——它占满线程且无法响应OnStop;改用Timer或Task.Delay+ 循环检测 - 示例片段:
private Timer _workTimer; protected override void OnStart(string[] args) { _workTimer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(1)); } private void DoWork(object state) { /* 实际业务逻辑 */ } - 务必在
OnStop中调用_workTimer?.Dispose()和清理资源,否则服务看似停了,线程还在后台跑
installutil.exe 安装失败的三个高频原因
不是路径不对就是权限不够,90% 的安装问题都出在这三处,不用急着查日志。
- 命令行没用管理员权限运行:右键「Windows Terminal (Admin)」或「CMD (管理员)」,普通用户执行
installutil.exe会静默失败,连错误都不打 -
installutil.exe版本和项目 .NET Framework 不匹配:项目是 4.7.2,就得用C:\Windows\Microsoft.NET\Framework64\v4.0.30319\installutil.exe(64位)或Framework\v4.0.30319\(32位),混用会报Could not load file or assembly - 服务程序集依赖缺失:比如用了
Newtonsoft.Json但没复制 DLL 到输出目录,installutil加载时直接抛FileNotFoundException;用ildasm或dotPeek检查引用,确保所有依赖都在bin\Debug下
真正麻烦的是服务启动后立刻闪退——这往往意味着 OnStart 内部抛了未捕获异常,而 Windows 服务默认不弹窗、不写事件日志。最稳妥的做法,是在 OnStart 开头加 try/catch 并强制写文件日志,否则你连哪一行崩了都不知道。










