Rom*_*kov 34 language-agnostic unit-testing windows-7
我们的单元测试会触发子进程,有时这些子进程会崩溃.发生这种情况时,会弹出一个Windows错误报告对话框,并且该过程保持活动状态,直到手动关闭该过程.这当然可以防止单元测试终止.
如何避免这种情况?
这是Win7中的一个示例对话框,其中包含常用设置:

如果我禁用了AeDebug注册表项,JIT调试选项就会消失:

如果我禁用检查解决方案(我似乎只能通过控制面板控制),它看起来像这样,但仍然出现并仍然停止程序死亡直到用户按下某些东西.记录WerAddExcludedApplication也具有此效果.

Rom*_*kov 56
jdehaan和Eric Brown的答案摘要,以及这个问题(另见这个问题):
注意这些解决方案也可能会影响其他错误报告,例如无法加载DLL或打开文件.
选项1:全局禁用
在整个用户帐户或机器上全局工作,这既是好处也是缺点.
设置[HKLM|HKCU]\Software\Microsoft\Windows\Windows Error Reporting\DontShowUI为1.更多信息:WER设置.
选项2:禁用应用程序
需要修改崩溃程序,在文档中描述为最佳实践,不适合库函数.
调用SetErrorMode :( SetErrorMode(SetErrorMode(0) | SEM_NOGPFAULTERRORBOX);或with SEM_FAILCRITICALERRORS).更多信息:禁用程序崩溃对话框(解释奇怪的呼叫安排).
选项2a:禁用功能:
需要修改崩溃程序,需要Windows 7/2008 R2(仅限桌面应用程序)或更高版本,在文档中描述为首选SetErrorMode,适用于线程安全库函数.
调用并重置SetThreadErrorMode:
DWORD OldThreadErrorMode = 0;
SetThreadErrorMode(SEM_FAILCRITICALERRORS,& OldThreadErrorMode);
…
SetThreadErrorMode (z_OldThreadErrorMode, NULL);
Run Code Online (Sandbox Code Playgroud)
更多信息:没有太多可用的?
选项3:指定处理程序
需要修改崩溃程序.
使用SetUnhandledExceptionFilter来设置简单地退出,可能与报告,并可能在清理尝试自己的结构化异常处理程序.
选项4:捕获作为例外
需要修改崩溃程序.仅适用于.NET应用程序.
将所有代码包装到全局try/catch块中.指定捕获异常的方法HandleProcessCorruptedStateExceptionsAttribute以及可能SecurityCriticalAttribute的方法.更多信息:处理损坏的状态异常
注意:这可能无法捕获托管调试助手导致的崩溃; 如果是这样,这些也需要在应用程序中禁用.
选项5:停止报告流程
在整个用户帐户上全局工作,但仅限于受控制的持续时间.
只要出现以下情况,请终止Windows错误报告流程:
var werKiller = new Thread(() =>
{
while (true)
{
foreach (var proc in Process.GetProcessesByName("WerFault"))
proc.Kill();
Thread.Sleep(3000);
}
});
werKiller.IsBackground = true;
werKiller.Start();
Run Code Online (Sandbox Code Playgroud)
但这仍然不完全是防弹,因为控制台应用程序可能会通过不同的错误消息崩溃,显然由一个名为的内部函数显示NtRaiseHardError:

唯一的解决方案是在非常高的级别(对于每个线程)捕获所有异常并正确终止应用程序(或执行另一个操作).
这是防止异常逃离您的应用并激活WER的唯一方法.
加成:
如果除了发生异常之外,您可以AssertNoThrow在另一个单元测试框架中使用(NUnit)或类似的方法来包含触发子进程的代码.通过这种方式,您还可以将其纳入单元测试报告中.在我看来,这是我能想到的最清晰的解决方案.
Addition2:正如下面的评论所示,我错了:你不能总是捕获异步异常,这取决于环境允许的内容.在.NET中,一些例外被阻止被捕获,在这种情况下,什么使我的想法毫无价值......
对于.NET:有一些复杂的解决方法涉及使用AppDomain,导致卸载AppDomain而不是整个应用程序的崩溃.太糟糕了...
http://www.bluebytesoftware.com/blog/PermaLink,guid,223970c3-e1cc-4b09-9d61-99e8c5fae470.aspx
http://www.develop.com/media/pdfs/developments_archive/AppDomains.pdf
编辑:
我终于明白了.使用.NET 4.0您可以将HandleProcessCorruptedStateExceptionsSystem.Runtime.ExceptionServices中的属性添加到包含try/catch块的方法中.这确实有效!也许不推荐但有效.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.ExceptionServices;
namespace ExceptionCatching
{
public class Test
{
public void StackOverflow()
{
StackOverflow();
}
public void CustomException()
{
throw new Exception();
}
public unsafe void AccessViolation()
{
byte b = *(byte*)(8762765876);
}
}
class Program
{
[HandleProcessCorruptedStateExceptions]
static void Main(string[] args)
{
Test test = new Test();
try {
//test.StackOverflow();
test.AccessViolation();
//test.CustomException();
}
catch
{
Console.WriteLine("Caught.");
}
Console.WriteLine("End of program");
}
}
}
Run Code Online (Sandbox Code Playgroud)