Windows服务重启异常:跨设备表现不一致及Error 109故障
问题描述
我有一个ReactJS应用,调用C#编写的后端API,这个API负责检查并重启处于停止状态的Windows服务。但该功能在不同设备上表现不一致:部分设备能正常启停服务,部分设备必须重启笔记本才能启动服务。手动停止服务时,会弹出错误提示:
Windows无法停止本地计算机上的XXX服务。
错误109:管道已结束。
服务虽然最终会停止,但无法通过API自动重启。
前端调用API的函数
checkWebService = () => { fetch(getAPIURL() + '/common/CheckWebService', { method: 'POST', headers: { 'Content-Type': 'application/json; charset=utf-8' } }).then((response) => { if (!response.ok) { throw response } return response //we only get here if there is no error }).then(data => { console.log('restart web service data: ', data); this.setState({ wsIsConnect: true, }, () => { this.doneLoading(false); }); }).catch(err => { console.log('restart web service err: ', err); this.setState({ wsIsConnect: false, }, () => { this.doneLoading(true); }); }); }
C#后端API代码
using System.ServiceProcess; //Activate the Windows Services if status it is stopped or pending [SupportedOSPlatform("windows")] //ServiceController only allows in Windows [HttpPost("CheckWebService")] public string CheckWebService() { try { ServiceController service = new ServiceController(ServiceName); Debug.WriteLine("checkwebservice status" + service.Status); if ((service.Status.Equals(ServiceControllerStatus.Stopped)) || (service.Status.Equals(ServiceControllerStatus.StopPending))) service.Start(); return "success"; } catch (Exception ex) { Log("Error", ex.ToString(), "CheckWebService"); return ex.ToString(); } }
问题分析与解决方案
核心问题拆解
- 错误109的本质:该错误说明服务停止时未正常关闭IPC管道,导致系统判定资源仍被占用,后续启动请求会因资源锁定失败。
- 后端逻辑短板:当前代码仅检查
Stopped和StopPending状态,未处理服务停止后的资源残留情况;且未等待状态稳定就执行启动,容易触发失败。
针对性修复方案
1. 优化后端服务状态处理逻辑
修改C#代码,增加状态等待、重试机制,确保服务状态稳定后再执行操作:
using System.ServiceProcess; using System.Threading; [SupportedOSPlatform("windows")] [HttpPost("CheckWebService")] public string CheckWebService() { try { using (ServiceController service = new ServiceController(ServiceName)) { Debug.WriteLine($"当前服务状态: {service.Status}"); // 等待停止中的服务完全终止 if (service.Status == ServiceControllerStatus.StopPending) { service.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30)); } // 带重试的启动逻辑 if (service.Status == ServiceControllerStatus.Stopped) { int retryCount = 3; bool startSuccess = false; while (retryCount > 0 && !startSuccess) { try { service.Start(); service.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30)); startSuccess = true; } catch (Exception startEx) { Debug.WriteLine($"启动失败,剩余重试次数: {retryCount-1},错误: {startEx.Message}"); retryCount--; Thread.Sleep(2000); service.Refresh(); // 刷新服务状态 } } if (!startSuccess) { throw new Exception("多次重试后仍无法启动服务"); } } return "success"; } } catch (Exception ex) { Log("Error", ex.ToString(), "CheckWebService"); return ex.ToString(); } }
2. 处理服务停止后的资源残留
- 检查XXX服务的代码,确保停止时释放所有IPC管道、文件句柄等资源,从根源避免"管道已结束"错误。
- 若无法修改服务代码,可在API中增加强制终止进程的逻辑(需谨慎使用,可能丢失未保存数据):
// 强制终止服务关联进程 private void ForceKillServiceProcess(string serviceName) { var processQuery = $"SELECT * FROM Win32_Service WHERE Name = '{serviceName}'"; using (var searcher = new ManagementObjectSearcher(processQuery)) { foreach (var serviceObj in searcher.Get()) { string processId = serviceObj["ProcessId"].ToString(); if (!string.IsNullOrEmpty(processId) && processId != "0") { try { Process process = Process.GetProcessById(int.Parse(processId)); process.Kill(); process.WaitForExit(10000); } catch (Exception ex) { Debug.WriteLine($"强制终止进程失败: {ex.Message}"); } } } } }
可在启动重试失败后调用该方法,再尝试启动服务。
3. 权限与环境差异排查
- 确保后端API运行账号拥有管理Windows服务的权限(如LocalSystem或管理员权限),部分设备可能因权限不足导致启动失败。
- 检查不同设备的UAC设置,级别过高可能限制服务操作,需确保API进程以管理员身份运行。
4. 前端错误处理优化
当前前端仅通过HTTP响应状态判断结果,无法反映服务实际状态。可修改API返回服务最终状态,前端据此更新UI:
// 前端修改后的响应处理逻辑 .then(response => response.json()) .then(data => { console.log('restart web service data: ', data); this.setState({ wsIsConnect: data.serviceStatus === 'Running', }, () => { this.doneLoading(false); }); })
后端对应返回结构:
return Json(new { result = "success", serviceStatus = service.Status.ToString() });
内容的提问来源于stack exchange,提问作者CnV
相关产品推荐
相关产品推荐

