Windows Server 2012中FileWatcher服务定时启停后报错咨询
我之前处理过类似的场景,虽然你的FileWatcher服务最终能正常启停,但事件查看器里的报错其实是控制台应用作为Windows服务运行时的环境兼容性问题。
为什么会出现报错?
错误信息里的核心提示很关键:当应用程序没有控制台或控制台输入从文件重定向时无法读取键。这说明你的代码里一定存在调用Console.ReadKey()的逻辑——当控制台应用被注册为Windows服务运行时,它是在无交互的会话0环境下执行的,没有真正的控制台窗口,此时调用Console.ReadKey()这种需要用户交互的方法就会抛出未处理的异常。
至于为什么服务还能成功停止:计划任务发送的停止信号会触发服务控制管理器的停止流程,虽然你的服务进程因为未处理异常终止了,但服务控制管理器最终还是会标记服务为“已停止”状态,所以你会同时看到“成功停止”和“停止失败/异常终止”的日志——前者是服务状态变更的结果,后者是进程异常终止的记录。
具体解决方案
针对这个问题,你可以按以下步骤修复:
定位并修改控制台读取逻辑
找到代码中所有Console.ReadKey()的调用,要么替换成错误提示里建议的Console.Read(),要么添加判断逻辑,只在交互模式(直接运行exe而非作为服务)时执行:// 示例:仅在用户交互模式下执行控制台按键读取 if (Environment.UserInteractive) { Console.WriteLine("按任意键退出..."); Console.ReadKey(); }添加全局异常捕获
在服务的停止处理逻辑中包裹try-catch,捕获这类预期的异常并记录为警告,避免系统将其标记为错误:protected override void OnStop() { try { // 你的服务停止清理逻辑 // 比如关闭文件监控器、释放资源等 } catch (InvalidOperationException ex) { // 写入事件日志作为警告,而非让系统抛出未处理异常 EventLog.WriteEntry("FileWatcher", $"服务停止时的预期异常:{ex.Message}", EventLogEntryType.Warning); } catch (Exception ex) { // 处理其他非预期异常 EventLog.WriteEntry("FileWatcher", $"服务停止时发生错误:{ex.ToString()}", EventLogEntryType.Error); } }确认服务启停命令的正确性
确保你的计划任务是通过标准服务控制命令来启停的,比如:- 停止服务:
sc stop FileWatcher - 启动服务:
sc start FileWatcher
避免直接运行FileWatcher.exe来启停,因为这会以控制台模式启动,而非服务模式。
- 停止服务:
总结
这个问题本质是控制台应用的交互逻辑在服务环境下不兼容导致的,只要修正代码中的控制台读取部分,就能消除事件查看器中的错误日志,同时不影响服务的正常启停。
内容的提问来源于stack exchange,提问作者MNeg

