可以防止Microsoft针对单个应用程序的错误报告吗? 我们有一个非托管C++应用程序,它利用第三方API来读取CAD文件。在某些损坏的CAD文件上,第三方库崩溃并使我们的EXE随之崩溃。因此,我们的主应用程序是一个单独的EXE,这样它就不会受到崩溃的影响。然而,我们最终会遇到恼人的Microsoft错误报告对话框
我不想在系统范围内禁用Microsoft错误报告。是否有一种方法可以关闭单个应用程序的错误报告功能,这样,如果它崩溃,它将在没有错误弹出对话框的情况下无声地崩溃?我一点也不确定,但可能或将对您有效?在Vista及更高版本上,可以使用API函数将指定的应用程序可执行文件从错误报告中排除。据我所知,XP和其他遗留操作系统版本上没有类似的选项 然而,由于WER只会在未处理的应用程序异常上启动,所以您应该能够通过向EXE添加“捕获所有”异常处理程序来抑制它。有关如何实现这一目标的一些想法,请参阅可以防止Microsoft针对单个应用程序的错误报告吗? 我们有一个非托管C++应用程序,它利用第三方API来读取CAD文件。在某些损坏的CAD文件上,第三方库崩溃并使我们的EXE随之崩溃。因此,我们的主应用程序是一个单独的EXE,这样它就不会受到崩溃的影响。然而,我们最终会遇到恼人的Microsoft错误报告对话框,c++,crash,unmanaged,C++,Crash,Unmanaged,我不想在系统范围内禁用Microsoft错误报告。是否有一种方法可以关闭单个应用程序的错误报告功能,这样,如果它崩溃,它将在没有错误弹出对话框的情况下无声地崩溃?我一点也不确定,但可能或将对您有效?在Vista及更高版本上,可以使用API函数将指定的应用程序可执行文件从错误报告中排除。据我所知,XP和其他遗留操作系统版本上没有类似的选项 然而,由于WER只会在未处理的应用程序异常上启动,所以您应该能够通过向EXE添加“捕获所有”异常处理程序来抑制它。有关如何实现这一目标的一些想法,请参阅 请注意
请注意,抑制所有未处理的异常通常是一个坏主意(例如,会导致您的应用程序无法通过Windows徽标认证),因此您不应该不加区别地使用此技术…是的,您可以做一些事情。在main()方法中调用SetUnhandledExceptionFilter()以注册回调。在Microsoft WER对话框显示之前,当没有人自愿处理异常时,将调用该函数 实际上,在回调中做一些事情充满了麻烦。该程序总是伴随着一些令人讨厌的事情而消亡,比如访问冲突异常。它经常被堆损坏所绊倒。当堆被toast时,尝试显示消息框让用户知道这样做很麻烦。死锁也总是潜伏在角落里,随时准备在没有任何诊断的情况下锁定程序 唯一安全的做法是使用一个助手进程来保护您的主进程。通过在回调中发送一个命名事件来唤醒它。使用内存映射文件为其提供所需的异常信息。当助手看到事件发出信号时,它几乎可以做任何它想做的事情。包括显示消息、进行小型转储。以及终止主进程
这正是Microsoft WerFault helper的工作原理。Hans Passant的答案是正确的。他还提出了一些关于不能在回调中执行太多操作的优点,因为流程的各个部分可能处于不稳定状态 但是,从描述问题的方式来看,除了告诉系统不要打开正常的崩溃对话框之外,您似乎什么都不想做。在这种情况下,这很容易,而且应该是安全的,无论碰撞过程中的哪些部分可能受到影响 使函数如下所示:
LONG WINAPI UnhandledExceptionCallback(PEXCEPTION_POINTERS pExceptPtrs)
{
if (IsDebuggerPresent())
// Allow normal crash handling, which means the debugger will take over.
return EXCEPTION_CONTINUE_SEARCH;
else
// Say we've handled it, so that the standard crash dialog is inhibited.
return EXCEPTION_EXECUTE_HANDLER;
}
在程序中的某个地方(可能尽早)设置回调:
SetUnhandledExceptionFilter(UnhandledExceptionCallback);
这应该做你想做的事情——允许该特定程序的任何崩溃安静地消失
然而,关于这一点还有一些需要注意的:任何时候,当您引入第三方组件(DLL、OCX等)时,其中一个组件也可能调用SetUnhandledExceptionFilter,从而用自己的组件替换您的回调。我曾经遇到一个ActiveX控件,它在实例化时会设置自己的回调。更糟糕的是,当它被销毁时,它无法恢复原始回调。这似乎是他们代码中的一个bug,但不管怎样,我必须采取额外的步骤,以确保在他们的控件关闭后,我所需的回调至少在应该恢复的时候被恢复。因此,如果有时您发现这似乎不适合您,即使您知道已正确设置回调,那么您可能会遇到类似的情况。在开发Delphi应用程序时,我发现自己正处于这种情况。我发现我需要两件事来可靠地抑制“应用程序已停止工作”对话框 调用
SetErrorMode(SEM_NOGPFAULTERRORBOX)代码>取消显示“应用程序已停止工作”对话框。但是Delphi的异常处理程序会显示一个消息框,其中包含运行时错误消息
为了抑制Delphi的异常处理程序,我使用一个自定义处理程序调用SetUnhandledExceptionFilter
,该处理程序通过调用Halt
终止进程
因此,运行易崩溃代码的Delphi客户端应用程序的框架变成:
function HaltOnException(const ExceptionInfo: TExceptionPointers): Longint; stdcall;
begin
Halt;
Result := 1; // Suppress compiler warning
end;
begin
SetErrorMode(SEM_NOGPFAULTERRORBOX);
SetUnhandledExceptionFilter(@HaltOnException);
try
DoSomethingThatMightCrash;
except
on E: Exception do
TellServerWeFailed(E.Message);
end;
end.
另外请注意,如果此崩溃是由未处理的结构化异常(访问冲突、堆栈溢出等)引起的,您可能需要研究使用结构化异常处理程序。你可以用它们来记录一些信息,然后静静地崩溃,或者做任何你想做的事情。这不起作用,什么都没有处理。它只会重新启动出错指令,以同样的方式崩溃。无止境的循环。无可否认,我写这篇文章是基于内存和一些旧代码的摘录的组合,而这些旧代码已经无法测试这篇文章了。但我只是把它放在一个快速测试程序中,我试图使用一个空指针使它崩溃,它看起来像预期的那样工作。我看到它静静地结束,而不是循环。如果我没有弄错的话,在您的UEF回调(IsDebuggerPresent
)中检查调试器是没有意义的,因为当调试器存在时,它们根本不会被回调。UEF通常是有问题和不可靠的。在一些罕见的情况下,系统不会回调它们,即使它们本应回调。此外,它们是全局性的,可能会被厚颜无耻的shell扩展、第三方库等覆盖,这些扩展调用WerAddExcludedApplication
(由用户“mdb”提出)或调用SetErrorMode
使用SEM_nogpfault terrorbo