1. Windows服务开发概述Windows服务是在Windows操作系统上以后台形式长期运行的应用程序。与普通桌面程序不同服务不需要用户交互界面能够在系统启动时自动运行即使用户注销也不会停止。这种特性使其非常适合执行需要持续运行的后台任务。作为.NET开发者我们最常遇到的服务开发场景包括数据同步服务如定时从数据库导出数据消息队列处理服务如RabbitMQ消费者系统监控服务如服务器资源监控告警文件处理服务如FTP文件自动下载处理定时任务服务如每天凌晨执行数据统计在.NET生态中我们主要通过两种方式开发Windows服务传统的Windows Service基于.NET Framework跨平台的Worker Service基于.NET Core/.NET 5本文重点介绍第一种方式即使用C#和.NET Framework开发经典的Windows服务。这种方式成熟稳定可以直接与Windows服务控制管理器集成适合需要深度系统集成的场景。2. 开发环境准备2.1 开发工具选择推荐使用Visual Studio 2022进行Windows服务开发。社区版即可满足需求它提供了完整的Windows服务项目模板和调试支持。如果使用旧版VS请确保安装.NET Framework开发组件。2.2 创建Windows服务项目在VS中新建项目时选择Windows服务(.NET Framework)模板。这里有几个关键选择需要注意目标框架版本建议选择.NET Framework 4.8这是.NET Framework的最终版本具有最好的兼容性和稳定性。项目结构模板会自动生成两个关键文件Program.cs服务宿主程序的入口Service1.cs默认服务实现类建议重命名为有意义的名称引用添加Windows服务项目需要以下核心引用System.ServiceProcess包含ServiceBase等核心类System.Configuration.Install用于服务安装注意如果找不到Windows服务模板可能是安装VS时未勾选.NET桌面开发工作负载中的.NET Framework项目模板组件。3. 服务核心逻辑实现3.1 服务类的基本结构每个Windows服务都需要继承自System.ServiceProcess.ServiceBase类并至少实现以下两个方法public class DataSyncService : ServiceBase { protected override void OnStart(string[] args) { // 服务启动时执行的逻辑 } protected override void OnStop() { // 服务停止时执行的逻辑 } }可选的重写方法还包括OnPause()服务暂停时触发OnContinue()服务从暂停恢复时触发OnShutdown()系统关闭时触发3.2 典型服务实现模式在实际开发中Windows服务通常采用以下架构模式主循环模式适合需要持续运行的服务private bool _isRunning; protected override void OnStart(string[] args) { _isRunning true; Task.Run(() { while(_isRunning) { // 执行核心业务逻辑 Thread.Sleep(1000); // 控制循环频率 } }); } protected override void OnStop() { _isRunning false; }定时器模式适合周期性执行的任务private Timer _timer; protected override void OnStart(string[] args) { _timer new Timer(DoWork, null, 0, 60000); // 每分钟执行一次 } private void DoWork(object state) { // 定时执行的业务逻辑 } protected override void OnStop() { _timer?.Dispose(); }事件驱动模式适合响应外部事件的服务private FileSystemWatcher _watcher; protected override void OnStart(string[] args) { _watcher new FileSystemWatcher(C:\WatchFolder); _watcher.Created OnFileCreated; _watcher.EnableRaisingEvents true; } private void OnFileCreated(object sender, FileSystemEventArgs e) { // 处理新文件 }3.3 日志记录实现可靠的日志系统对服务调试和运维至关重要。推荐使用log4net进行日志记录安装log4net NuGet包Install-Package log4net添加log4net.config配置文件log4net appender nameRollingFile typelog4net.Appender.RollingFileAppender file valuelogs/service.log / appendToFile valuetrue / rollingStyle valueSize / maxSizeRollBackups value10 / maximumFileSize value10MB / layout typelog4net.Layout.PatternLayout conversionPattern value%date [%thread] %-5level %logger - %message%newline / /layout /appender root level valueINFO / appender-ref refRollingFile / /root /log4net在服务中初始化log4netprivate static readonly ILog logger LogManager.GetLogger(typeof(DataSyncService)); protected override void OnStart(string[] args) { XmlConfigurator.Configure(new FileInfo(log4net.config)); logger.Info(Service started successfully); }4. 服务安装与部署4.1 添加服务安装程序在服务设计器中右键点击选择添加安装程序VS会自动生成两个组件serviceInstaller1配置服务显示名称、描述等元信息serviceProcessInstaller1配置服务运行账户关键属性设置建议// serviceInstaller1 serviceInstaller1.ServiceName DataSyncService; serviceInstaller1.DisplayName Data Sync Service; serviceInstaller1.Description Synchronizes data between databases; serviceInstaller1.StartType ServiceStartMode.Automatic; // 自动启动 // serviceProcessInstaller1 serviceProcessInstaller1.Account ServiceAccount.LocalSystem; // 使用系统账户4.2 使用InstallUtil安装服务编译项目后使用.NET Framework自带的InstallUtil工具安装服务以管理员身份打开命令提示符导航到.NET Framework目录如C:\Windows\Microsoft.NET\Framework\v4.0.30319执行安装命令InstallUtil.exe C:\path\to\your\service.exe4.3 批处理脚本自动化创建install.bat简化安装过程echo off set SERVICE_EXEDataSyncService.exe set INSTALLUTIL%windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe echo Installing %SERVICE_EXE%... %INSTALLUTIL% %~dp0%SERVICE_EXE% pause对应的uninstall.batecho off set SERVICE_EXEDataSyncService.exe set INSTALLUTIL%windir%\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe echo Uninstalling %SERVICE_EXE%... %INSTALLUTIL% /u %~dp0%SERVICE_EXE% pause5. 服务管理与调试技巧5.1 服务控制命令常用服务管理命令启动服务net start DataSyncService停止服务net stop DataSyncService查询状态sc query DataSyncService5.2 调试技巧调试Windows服务的几种方法附加到进程启动服务后在VS中选择调试-附加到进程选择服务进程进行调试日志调试在关键代码位置添加详细日志使用log4net的DEBUG级别记录内部状态控制台模式static void Main() { if (Environment.UserInteractive) // 调试模式 { var service new DataSyncService(); service.OnStart(null); Console.WriteLine(Running in console mode...); Console.ReadLine(); service.OnStop(); } else // 服务模式 { ServiceBase.Run(new ServiceBase[] { new DataSyncService() }); } }5.3 性能监控使用PerformanceCounter监控服务性能private PerformanceCounter _cpuCounter; private PerformanceCounter _memCounter; protected override void OnStart(string[] args) { _cpuCounter new PerformanceCounter(Process, % Processor Time, Process.GetCurrentProcess().ProcessName); _memCounter new PerformanceCounter(Process, Working Set, Process.GetCurrentProcess().ProcessName); Task.Run(() { while(true) { float cpu _cpuCounter.NextValue(); float mem _memCounter.NextValue() / 1024 / 1024; // MB logger.Info($CPU: {cpu}%, Memory: {mem}MB); Thread.Sleep(5000); } }); }6. 高级主题与最佳实践6.1 服务恢复选项配置服务崩溃后自动恢复serviceInstaller1.ServicesDependedOn new string[] { MSMQ }; // 依赖服务 serviceInstaller1.RecoveryOptions new ServiceRecoveryOptions { FirstFailureAction ServiceRecoveryAction.RestartService, SecondFailureAction ServiceRecoveryAction.RestartService, SubsequentFailureAction ServiceRecoveryAction.RunProgram, DaysToResetFailAcount 1, RunProgramCommand C:\scripts\alert_admin.bat };6.2 多服务宿主单个exe可以托管多个服务static void Main() { ServiceBase[] servicesToRun new ServiceBase[] { new DataSyncService(), new MonitoringService() }; ServiceBase.Run(servicesToRun); }6.3 安全最佳实践服务账户选择LocalSystem最高权限慎用NetworkService适合需要网络访问的服务自定义域账户企业环境推荐权限最小化原则仅授予服务所需的最小权限使用文件系统ACL限制访问安全审计EventLog.WriteEntry(DataSyncService, Security alert: invalid access attempt, EventLogEntryType.Warning, 1001);6.4 服务版本更新策略停止旧版本服务备份配置和数据文件安装新版本恢复配置启动新服务可以使用PowerShell脚本自动化此过程$serviceName DataSyncService $backupDir C:\backup\$(Get-Date -Format yyyyMMdd) Stop-Service $serviceName Copy-Item C:\Program Files\DataSync\config $backupDir -Recurse Copy-Item C:\Program Files\DataSync\DataSyncService.exe $backupDir # 安装新版本... Start-Service $serviceName7. 常见问题排查7.1 安装失败问题问题1InstallUtil报错拒绝访问原因未使用管理员权限运行cmd解决以管理员身份运行命令提示符问题2未能加载文件或程序集错误原因32/64位不匹配解决使用正确版本的InstallUtilFramework vs Framework647.2 运行时问题问题1服务启动后立即停止排查步骤检查事件查看器中的应用程序日志确保OnStart方法没有抛出异常确认服务账户有足够权限问题2服务无法访问网络资源排查步骤确认服务账户有网络权限检查防火墙设置使用Process Monitor工具监控文件/注册表访问7.3 调试技巧使用Windows事件日志记录详细错误try { // 业务代码 } catch (Exception ex) { EventLog.WriteEntry(Application, $Service error: {ex.Message}\n{ex.StackTrace}, EventLogEntryType.Error, 1001); throw; }8. 现代化替代方案虽然传统的Windows Service仍然适用但.NET Core引入的Worker Service提供了更现代的替代方案优势对比跨平台支持Windows/Linux/macOS更简单的生命周期管理更好的依赖注入支持与ASP.NET Core集成创建Worker Service// Program.cs Host.CreateDefaultBuilder(args) .UseWindowsService() // 添加Windows服务支持 .ConfigureServices(services { services.AddHostedServiceDataSyncWorker(); }) .Build() .Run(); // Worker实现 public class DataSyncWorker : BackgroundService { protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // 执行任务 await Task.Delay(1000, stoppingToken); } } }迁移建议新项目优先考虑Worker Service现有项目如果不需要跨平台可以继续使用Windows Service复杂服务可以考虑逐步迁移组件