)
1. Windows服务开发基础认知第一次接触Windows服务开发时我踩过的最大坑就是把它当成普通控制台程序来调试。直到运行时弹出无法从命令行启动服务的提示框才恍然大悟——这玩意儿根本不能用F5直接运行Windows服务本质上是一种没有用户界面的后台程序它会在系统启动时自动运行即使用户注销也不会停止。这种特性特别适合用来做消息队列处理、定时任务或者系统监控。记得去年给客户做文件同步系统时最初用的是控制台程序结果用户一关机任务就中断了。后来改用Windows服务设置好自动启动后客户再也不用担心半夜备份任务失败了。这里有个实用建议如果你需要长时间运行的后台任务优先考虑Windows服务而不是计划任务因为服务更稳定且资源占用可控。2. 创建服务项目的正确姿势在Visual Studio 2022中新建项目时很多人会忽略一个关键选项必须选择.NET Framework模板目前最新版是4.8。我就见过有同事选了.NET Core的Worker Service模板结果死活找不到安装入口。具体操作路径新建项目 → Windows服务(.NET Framework) → 命名比如FileSyncService。创建完成后会看到两个关键文件Program.cs服务宿主的主入口Service1.cs默认服务类建议立即重命名这里有个隐藏坑点服务类必须重写OnStart和OnStop方法否则安装时会报错。我建议一开始就把所有可重写方法都加上protected override void OnStart(string[] args) { // 初始化操作写在这里 logger.Info(服务启动初始化...); } protected override void OnStop() { // 清理资源操作写在这里 logger.Info(服务正在停止...); }3. 日志配置的实战技巧没有日志的服务就像蒙眼开车——出问题时根本不知道翻在哪。我强烈推荐用log4net而不是Windows事件日志因为它的滚动归档和分级过滤功能更强大。配置步骤新建LogConfig文件夹添加log4net.config文件设置文件属性复制到输出目录为始终复制通过NuGet安装log4net包在AssemblyInfo.cs添加配置指向[assembly: log4net.Config.XmlConfigurator( ConfigFile LogConfig/log4net.config, Watch true)]分享一个真实案例有次服务突然CPU飙高幸亏我们配置了DEBUG级别日志最终发现是某个循环缺少退出条件。如果只用事件日志这种问题可能要排查好几天。4. 服务安装的核心要点最让人头疼的环节来了——安装部署。传统做法是用InstallUtil.exe但这里至少有3个坑等着你路径问题32位和64位系统用的InstallUtil路径不同32位C:\Windows\Microsoft.NET\Framework\v4.0.3031964位C:\Windows\Microsoft.NET\Framework64\v4.0.30319权限问题必须用管理员身份运行CMD否则会报拒绝访问错误。我习惯在批处理开头加权限检查echo off :: 检查管理员权限 net session nul 21 if %errorLevel% neq 0 ( echo 请用管理员身份运行 pause exit /b )编码问题路径包含中文时会出现乱码解决方法是在bat开头加chcp 65001 nul5. 一键部署脚本大全手动敲命令太麻烦我整理了全套批处理脚本安装服务.batecho off chcp 65001 nul set SERVICE_NAMEMyDemoService set EXE_PATH%~dp0MyDemoService.exe echo 正在安装服务... InstallUtil %EXE_PATH% sc config %SERVICE_NAME% start auto net start %SERVICE_NAME% if %errorLevel% equ 0 ( echo 服务安装成功 ) else ( echo 安装失败请检查日志 ) pause卸载服务.batecho off chcp 65001 nul set SERVICE_NAMEMyDemoService set EXE_PATH%~dp0MyDemoService.exe echo 正在停止服务... net stop %SERVICE_NAME% echo 正在卸载服务... InstallUtil /u %EXE_PATH% if %errorLevel% equ 0 ( echo 卸载成功 ) else ( echo 卸载失败尝试强制删除... sc delete %SERVICE_NAME% ) pause这些脚本要和服务exe放同一目录右键以管理员身份运行即可。实测比手动操作效率提升10倍不止。6. 高频踩坑解决方案坑1服务启动后立即停止通常是OnStart方法执行时间超过30秒需要添加状态报告// 在OnStart开头添加 ServiceStatus serviceStatus new ServiceStatus { dwCurrentState ServiceState.SERVICE_START_PENDING, dwWaitHint 100000 }; SetServiceStatus(this.ServiceHandle, ref serviceStatus); // 初始化完成后更新状态 serviceStatus.dwCurrentState ServiceState.SERVICE_RUNNING; SetServiceStatus(this.ServiceHandle, ref serviceStatus);坑2安装时提示依赖项缺失检查目标平台是否一致x86程序不能用64位InstallUtil安装。建议在项目属性→生成里明确指定平台。坑3服务无法写入日志给服务账户赋权计算机管理→本地用户和组→组把服务账户加入Performance Log Users组。7. 高级运维技巧多实例部署通过sc命令可以实现sc create MyService_Instance1 binPath C:\Path\To\Service.exe服务恢复策略在服务属性→恢复中设置第一次失败时重启服务第二次失败时运行特定程序。内存监控在OnStart中添加性能计数器PerformanceCounter ramCounter new PerformanceCounter( Memory, Available MBytes); float availableMB ramCounter.NextValue();最近在金融项目中发现配合NSSM(非官方服务管理器)可以更方便地管理服务生命周期但考虑到合规性生产环境还是建议用原生方案。