【问题标题】:Unhandled exception in Windows Service when using catch(Exception)使用 catch(Exception) 时 Windows 服务中未处理的异常
【发布时间】:2013-09-05 14:33:03
【问题描述】:

我遇到了一个非常令人沮丧的问题。我正在编写一个 Windows 服务,它的作用类似于 TCPServer(我不确定技术术语,但该服务通过 tcp 处理一组客户端之间的通信)。

我的问题是服务随机崩溃(至少我不知道是什么原因导致异常)并且windows应用程序日志包含一条VsJITDebugger(EventID 4096)错误消息:

SDUNoteTCPServerService.exe [1028] 中出现未处理的 win32 异常。刚进- 调试此异常的时间失败并出现以下错误:无法调试器 因为没有用户登录而启动。

我不是 100% 确定 VsJITDebugger 是什么,但据我通过谷歌搜索发现 VsJITDebugger 是某种使用 Visual Studio 来澄清未处理异常的工具。有时我还会在 VsJITDebugger 错误消息之前看到以下 .Net Runtime (EventID: 1026) 错误消息:

应用程序:SDUNoteTCPServerService.exe 框架版本:v4.0.30319 说明:进程因未处理的异常而终止。 异常信息:System.ComponentModel.Win32Exception 堆: 在 System.Diagnostics.EventLogInternal.InternalWriteEvent(UInt32,UInt16, System.Diagnostics.EventLogEntryType、System.String[]、Byte[]、System.String) 在 System.Diagnostics.EventLogInternal.WriteEntry(System.String, System.Diagnostics.EventLogEntryType,Int32,Int16,字节 []) 在 System.Diagnostics.EventLog.WriteEntry(System.String, System.Diagnostics.EventLogEntryType, Int32) 在 TCPServer.TCPServerListener+AsynchronousSocketListener.WriteCustomSocketObjectMessagesToLog (System.String, System.Diagnostics.EventLogEntryType, Int32) 在 TCPServer.TCPServerListener+CustomSocketObject.SendMessageToClientThread() 在 System.Threading.ThreadHelper.ThreadStart_Context(System.Object) 在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback,System.Object,布尔值) 在 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) 在 System.Threading.ThreadHelper.ThreadStart()

如 .Net 运行时错误消息中所述,当我尝试在 EventLog 中写入有关捕获的异常的详细信息时,会引发未处理的错误。异常总是在套接字的 BeginReceive 方法的回调函数中抛出。

我不知道为什么这个异常首先会导致服务崩溃,因为我在 Socket.BeginReceive 方法的回调函数中使用 try{}catch(Exception) 捕获一般异常,但我无法提取任何关于捕获的异常的信息,因为这个未处理的异常被抛出。

任何想法可能是什么问题?感谢所有回复。

注意:该服务在 Windows Server 2003 (SP2) 上运行。已安装 Visual Studio 2008。

编辑:WriteCustomSocketObjectMessagesToLog 看起来像这样(事件日志对象是 AsynchronousSocketListener 类的属性):

private void WriteExceptionToLog(string customstartmessage, Exception ex) { 尝试 { eventlog.WriteEntry(customstartmessage, EventLogEntryType.Error); eventlog.WriteEntry(ex.Message, EventLogEntryType.Error, 5); eventlog.WriteEntry(ex.Source, EventLogEntryType.Error, 5); eventlog.WriteEntry(ex.StackTrace, EventLogEntryType.Error, 5); } 捕捉(例外) { eventlog.WriteEntry("报告异常失败", EventLogEntryType.Error); } }

编辑 2:

我发现了问题所在。事件日志报告已满。难怪那时我不能写信给它。我通过将类库转换为控制台应用程序发现了问题。当我开始编写 TCPServer 类时,我也这样做了,但当时我使用 WriteLine 方法将错误写入控制台。这次控制台应用程序写入创建的事件日志,未处理的异常被写入控制台(如果这是控制台应用程序的默认行为,我不这样做,因为我没有为此进行任何编码)。我的 Windows 服务中未处理的错误很可能是这样的:

未处理的异常:System.ComponentModel.Win32Exception:事件日志文件已满 在 System.Diagnostics.EventLogInternal.InternalWriteEvent(UInt32 eventID,UInt16 类别,EventLogEntryType 类型,String[] 字符串,Byte[] rawData,String currentMachineName) 在 System.Diagnostics.EventLogInternal.WriteEntry(字符串消息,EventLogEntryType 类型,Int32 eventID,Int16 类别,Byte[] rawData) 在 System.Diagnostics.EventLog.WriteEntry(字符串消息) 在 TCPServer.Program.Main(String[] args)

现在我可能只需要处理这个问题。处理此错误的更好解决方案是什么?每次抛出错误时以编程方式保存和清空事件日志?无限增加事件日志大小(这可能是个好主意吗?)?还有其他建议吗?

【问题讨论】:

  • 运行服务的账号是否有权限在想要的位置写入磁盘?
  • 我的水晶球说,当您的 catch 处理程序尝试将事件写入 Windows 事件日志时,它也崩溃了。所以当然,你不知道它为什么会崩溃,我们也不知道。如果您无法在该机器上轻松获得调试器,请使用 DebugDiag 之类的工具。
  • 目前该服务是在具有管理员权限的帐户下运行的,所以我认为权限不是这里的问题,但我也不是 100% 确定。
  • @HansPassant,没听说过,但我一定会看看那个工具。

标签: c# windows-services unhandled-exception


【解决方案1】:

正如在第二次编辑中所写,我发现问题是尝试写入时事件日志已满。我记录了很多,EventLog 的默认行为是 512 左右的 MaximumKilobytes 并保留超过 7 天的条目。我更改了配置,使 MaximumKilobytes 等于 25 MB,并根据需要覆盖条目。

【讨论】:

    【解决方案2】:

    为您的 AppDomain UnhandledException 事件定义一个处理程序:

    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
    
    void MyHandler(object sender, UnhandledExceptionEventArgs e)
    {
        // See the exception context here using e.ExceptionObject 
    }
    

    【讨论】:

    • 我很确定我已经尝试过这个没有任何运气,但我会再试一次。我需要在哪里实施以确保正确实施?在服务初始化期间?
    【解决方案3】:

    如果要捕获异常,需要在AsynchronousSocketListener.WriteCustomSocketObjectMessagesToLog 中添加异常处理程序。 AsynchronousSocketListener 类嵌套在 TCPServerListenerTCPServer 命名空间中。我假设这个类是你或你的组织已经实现的。

    不幸的是,在一些尝试写入事件日志的代码中抛出了异常,因此如果异常的根本原因是内存耗尽,那么捕获异常并尝试记录它可能会有些困难。

    查看System.Diagnostics.EventLogInternal 类中InternalWriteEvent 的.NET 4.0 源代码,似乎只有一个地方可以抛出Win32Exception,那就是如果对ReportEvent 函数的调用失败。

    Win32Exception 将包含 Windows 错误代码。根据ReportEvent 文档,可能有四个错误代码:

    • ERROR_INVALID_PARAMETER (87)
    • ERROR_NOT_ENOUGH_MEMORY (8)
    • RPC_S_INVALID_BOUND (1734)
    • RPC_X_BAD_STUB_DATA (1783)
    • 也有可能出现其他错误代码

    发现Win32Exception 的错误代码有望帮助您了解问题的根源。

    【讨论】:

    • 我已经提交了 AsynchronousSocketListener.WriteCustomSocketObjectMessagesToLog 方法的代码,你可以看到我在写入事件日志时已经使用了 try catch。
    • @KevinGram:在eventlog.WriteEntry 周围放置一个try-catch,然后在使用eventlog.WriteEntry 记录任何异常的catch 处理程序中不是一个好策略。 Hans Passant 已经用他的水晶球猜到了。
    • 我现在知道了。我非常感谢您为帮助我解决问题所做的努力。幸运的是我想通了,但我不能在明天之前标记我的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    • 2010-09-08
    • 2011-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多