如何解决事件日志中的.NET 2.0错误报告消息?

我在一个名为EVEMon的开源产品上工作,用C#编写,面向.NET 2.0平台,我有一个用户遇到了我们无法解决的奇怪的.NET崩溃问题。

事件类型:错误
事件源:.NET Runtime 2.0错误报告
活动类别:无
事件ID:5000
日期:2009年4月29日
时间:晚上10:58:10
用户:N / A.
电脑:删除了这个
描述:
 EventType clr20r3,P1 evemon.exe,P2 1.2.7.1301,P3 49ea37c8,P4
 system.windows.forms,P5 2.0.0.0,P6 4889dee7,P7 6cd3,P8 18,P9
 system.argumentexception,P10 NIL。

数据:
 //以上描述的hex表示

应用程序本身崩溃而不显示错误(尽管有error handlingUI),上述消息被复制出Windows事件日志。 最终用户已重新安装.NET并更新到最新版本。 .PDB文件随程序的每个发行版本一起分发,以帮助调试和测试,有问题的用户可以获得正确版本的EVEMon的完整PDB文件。

是否有一种特定的,经过试验和测试的技术来分析和诊断这种类型的崩溃? 如果有的话,有哪些工具和技术可以帮助调试?

特别谢谢

我要特别感谢Steffen Opel,并强调他的答案虽然没有直接回答我提出的问题,但我的代码库解决了更大的问题,即全局error handling缺少一个重要组件。

这就是我如何解决崩溃的最终用户的问题。

  1. 下载并安装适用于Windows的调试工具, url为http://www.microsoft.com/whdc/devtools/debugging/default.mspx

  2. 安装工具后(默认情况下它们最终会转到C:\ Program Files \)启动命令行窗口。

  3. 切换到包含adplus的目录(例如“C:\ Program Files \ Debugging Tools for Windows(x86)”)。

  4. 运行follwing命令。 这将启动应用程序并附加adplus。

adplus -crash -o C:\debug\ -FullOnFirst -sc C:\path\to\your\app.exe

创建崩溃转储后

应用程序崩溃后启动WinDbg并加载在C:\ debug中创建的.dmp文件。 (文件 – >打开崩溃转储)

执行这些命令以查看堆栈跟踪并希望找到问题。

加载SOS以进行调试

  • 预.NET 4.0
 .loadby sos mscorwks 
  • .NET 4.0
 .loadby sos clr 

要查看堆栈跟踪

 !clrstack 

查看更有用的堆栈跟踪

 !clrstack –p 

在一个对象内部戳…也许看看是什么导致了exception

 !do 

例如,这是应用程序因IOexception而随机出错的结果。 WinDbg指出了被引用的路径不正确。

 0:009> !do 017f2b7c Name: System.String MethodTable: 790fd8c4 EEClass: 790fd824 Size: 124(0x7c) bytes (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll) String: \\server\path\not_here.txt Fields: MT Field Offset Type VT Attr Value Name 79102290 4000096 4 System.Int32 1 instance 54 m_arrayLength 79102290 4000097 8 System.Int32 1 instance 53 m_stringLength 790ff328 4000098 c System.Char 1 instance 5c m_firstChar 790fd8c4 4000099 10 System.String 0 shared static Empty >> Domain:Value 00161df8:790d884c << 7912dd40 400009a 14 System.Char[] 0 shared static WhitespaceChars >> Domain:Value 00161df8:014113e8 << 

窥视您的源代码(主干)表明您的未处理exception处理在Windows窗体应用程序方面似乎不完整:

您需要处理非UI线程exception和UI线程exception:

  • 对于前者,您需要通过AppDomain.CurrentDomain.UnhandledException实现CLR未处理的exception处理程序,该处理程序已经就绪。

  • 对于后者,您需要通过Application.ThreadException实现Windows Forms未处理的exception处理Application.ThreadException ,这似乎缺失; 这确实可以产生你正在目睹的那些问题。 有关实现示例,请参阅Application.ThreadException事件的 MSDN文档。

请注意,现在您通过Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)明确禁止捕获未处理的Windows窗体exception,您需要将其更改为UnhandledExceptionMode.CatchException以启用路由到Application.ThreadException的处理Application.ThreadException ,正如Jehof正确建议的那样已经。

用户使用什么操作系统(Windows XP,Windows Vista等)?

如果Windows Vista尝试禁用“问题报告和解决方案function”(控制面板 – >问题报告和解决方案 – >更改设置 – >高级设置 – >关闭我的程序,问题报告)

或尝试设置

  Application.SetUnhandledExceptionMode( UnhandledExceptionMode.CatchException ); 

这将始终将exception路由到ThreadException处理程序。

简而言之:应用程序中存在未处理的exception。

如果您有权访问该计算机(通过远程访问等),请尝试安装Visual Studio Express并启动该应用程序。 您应该看到一个对话框,提供了使用Visual Studio的新实例调试应用程序的机会。

也可能是某些东西阻止Windows窗体正确初始化。 我看过论坛post表明字体问题会导致这种情况 – 确保用户安装了应用程序所需的字体加上常用的默认设置,如MS SansSerif,Arial,Tahoma,Times等。

如果没有…尝试在PC上牺牲一只鸡。 每次都有魅力!

我们在线程代码中遇到了exception问题。 如果你生成一个新线程并忘记在线程方法中处理exception,那么应用程序只是“停止” – 没有错误消息,没有任何内容,只有事件日志中的条目。 甚至不会触发UnhandledExceptionHandler

也许这样的事情是什么原因?

…如果你能够联系那个痛苦的用户,这里有一个

想法:记录预执行阶段

而不是创建program.exe的快捷方式,而是创建program.exe的快捷方式,这将是

 echo "Pre-start" > stage.txt start program.exe 

因此, Program.cs的第一行将是

 File.WriteAllLines("stage.txt", "Program execution started."); 

AppDomain.UnhandledException的处理程序中,第一行将是

 File.WriteAllLines("stage.txt", "Unhandled exception has been caught."); 

此外,请确保处理程序不分配内存或资源 – 在程序启动时预先分配它们。 处理程序仅触发写入日志。

评论

stage.txt (由用户发送)很可能包含“预启动”。 这种情况发生在第三方.dll中引发exception – 甚至在程序启动之前。

在这种情况下,您将需要一个简单的检查程序,它不会引用program.exe执行的程序集,但会引用Assembly.Load(...)它们。

PS

stage.txt应放在%APPDATA%下,而不是程序文件中。

我在Server 2003上发现了一个有趣的案例和另一个很好的讨论 。

您应该通过将该特定版本的.pdb文件发送给用户(放在.exe旁边)并让它们重现崩溃来获得更详细的堆栈跟踪。

您应该在代码中处理AppDomain.UnhandledException

问了一个类似的问题 。 也见相关的。