9

我在一个名为EVEMon的开源产品上工作,该产品是用 C# 编写的,针对 .NET 2.0 平台,我有一个用户正在遭受我们无法解决的奇怪的 .NET 崩溃。

事件类型:错误
事件源:.NET 运行时 2.0 错误报告
事件类别:无
事件编号:5000
日期:2009 年 4 月 29 日
时间:晚上 10:58:10
用户:不适用
电脑:删除了这个
描述:
事件类型 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 无。

数据:
//以上描述的十六进制表示

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

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

特别感谢

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

4

8 回答 8

18

这就是我为崩溃的最终用户解决问题的方法。

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

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

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

  4. 运行以下命令。这将启动应用程序并附加 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

戳一个对象..也许看看是什么导致了异常

!do <address>

例如,这是由于应用程序随机出现 IO 异常而导致的结果。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 <<
于 2009-07-04T08:00:20.503 回答
5

查看您的源代码(主干)表明您的未处理异常处理对于 Windows 窗体应用程序似乎不完整:

您需要同时处理UI 线程异常和 UI 线程异常:

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

  • 对于后者,您需要通过 实现 Windows 窗体未处理的异常处理程序Application.ThreadException,这似乎丢失了;这确实可以产生您正在目睹的那些问题。有关实现示例,请参阅Application.ThreadException Event的 MSDN 文档。

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

于 2009-07-04T13:55:48.897 回答
3

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

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

或者尝试设置

  Application.SetUnhandledExceptionMode( UnhandledExceptionMode.CatchException );

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

于 2009-07-01T08:54:08.730 回答
2

我们遇到了线程代码中的异常问题。如果您生成一个新线程并忘记在线程方法中处理异常,则应用程序只会“停止” - 没有错误消息,什么都没有,而只是事件日志中的一个条目。即使这样UnhandledExceptionHandler也不会触发。

也许是这样的原因?

于 2009-07-01T07:51:48.137 回答
2

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

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

也可能是有一些东西阻止了 Windows 窗体正确初始化。我已经看到论坛帖子表明字体问题可能导致这种情况——确保用户安装了您的应用程序需要的字体以及通常的默认值,例如 MS SansSerif、Arial、Tahoma、Times 等。

失败了...尝试在PC上牺牲一只鸡。每次都有魅力!

于 2009-06-30T15:16:01.943 回答
1

...如果您能够联系到那个受苦的用户,这里有一个

想法:记录预执行阶段

不要给你的program.exe做一个快捷方式,而是给 做一个快捷方式program.bat,这将

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包含“预启动”。这发生在第 3 方 .dll 中引发异常时——甚至在您的程序启动之前。

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

附言

stage.txt应该放在 %APPDATA% 下的某个地方,而不是在 Program Files 中。

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

于 2009-07-02T20:09:35.423 回答
0

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

于 2009-05-02T10:05:17.467 回答
0

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

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

于 2009-07-02T14:20:00.803 回答