能否阻止单个应用程序的 Microsoft 错误报告?

发布于 2024-09-12 16:04:48 字数 239 浏览 7 评论 0原文

我们有一个非托管 C++ 应用程序,它利用第 3 方 API 来读取 CAD 文件。对于某些损坏的 CAD 文件,第 3 方库崩溃并导致我们的 EXE 崩溃。因此,我们的主应用程序是一个单独的 EXE,这样它就不会受到崩溃的影响。然而,我们最终会遇到烦人的 Microsoft 错误报告对话框。

我不想在系统范围内禁用 Microsoft 错误报告。有没有一种方法可以关闭单个应用程序的错误报告,以便在它崩溃时,它会安静地崩溃而不会弹出错误对话框?

We have an unmanaged C++ application that utilizes 3rd party APIs to read CAD files. On certain corrupted CAD files, the 3rd party library crashes and brings our EXE down with it. Because of this our main application is a separate EXE and in this way it does not get affected by the crash. Howevever, we end up with annoying Microsoft Error Reporting dialogs.

I do not want to disable Microsoft Error Reporting system wide. Is there a way to turn off error reporting for a single application, so that if it crashes, it crashes silently without error popup dialogs?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

人疚 2024-09-19 16:04:48

在 Vista 及更高版本中,WerAddExcludedApplication API 函数可用于排除从错误报告中指定应用程序可执行文件。据我所知,XP 和其他旧操作系统版本上没有类似的选项。

然而,由于 WER 只会在未处理的应用程序异常时启动,因此您应该能够通过向 EXE 添加“包罗万象”的异常处理程序来抑制它。有关如何处理的一些想法,请参阅向量异常处理为了实现这一点。

请注意,抑制所有未处理的异常通常是一个坏主意(例如,会导致您的应用程序无法通过 Windows 徽标认证),因此您不应不加区别地使用此技术...

On Vista and above, the WerAddExcludedApplication API function can be used to exclude a specified application executable from error reporting. As far as I'm aware, there's no similar option on XP and other legacy OS versions.

However, since WER will only kick in on unhandled application exceptions, you should be able to suppress it by adding a "catch-all" exception handler to your EXE. See vectored exception handling for some ideas on how to achieve that.

Note that suppressing all unhandled exceptions is generally a bad idea (and will, for example, cause your app to fail Windows Logo certification), so you should not use this technique indiscriminately...

庆幸我还是我 2024-09-19 16:04:48

是的,你可以做点什么。在 main() 方法中调用 SetUnhandledExceptionFilter() 来注册回调。当没有人自愿处理异常时,就在 Microsoft WER 对话框出现之前,它将被调用。

实际上在回调中做一些事情充满了麻烦。程序总是因为像 AccessViolation 异常这样令人讨厌的事情而死掉。这通常会因堆损坏而被绊倒。当堆被烘烤时,尝试执行诸如显示消息框之类的操作来让用户知道是很麻烦的。死锁也总是潜伏在拐角处,准备在没有任何诊断的情况下锁定程序。

唯一安全的做法是有一个辅助进程来保护您的主进程。通过在回调中发出命名事件信号来唤醒它。通过内存映射文件为其提供所需的异常信息。当助手看到事件信号时,它几乎可以做任何它想做的事情。包括显示消息、进行小型转储。并终止主进程。

这正是 Microsoft WerFault 帮助程序的工作原理。

Yeah, there's something you can do. Call SetUnhandledExceptionFilter() in your main() method to register a callback. It will be called when nobody volunteers to handle the exception, just before the Microsoft WER dialog shows up.

Actually doing something in that callback is fraught with trouble. The program has died with, invariably, something nasty like an AccessViolation exception. Which often is tripped by heap corruption. Trying to do something like displaying a message box to let the user know is troublesome when the heap is toast. Deadlock is always lurking around the corner too, ready to just lock up the program without any diagnostic at all.

The only safe thing to do is to have a helper process that guards your main process. Wake it up by signaling a named event in your callback. Give it the exception info it needs with a memory-mapped file. The helper can do pretty much anything it wants when it sees the event signaled. Including showing a message, taking a minidump. And terminating the main process.

Which is exactly how the Microsoft WerFault helper works.

慵挽 2024-09-19 16:04:48

Hans Passant 关于 SetUnhandledExceptionFilter 的回答是正确的。他还提出了一些关于在回调中不能做太多事情的好观点,因为过程的各个部分可能处于不稳定状态。

但是,从描述问题的方式来看,除了告诉系统不要显示正常的崩溃对话框之外,您似乎不想做任何事情。在这种情况下,无论崩溃可能影响到进程的哪些部分,这都很容易并且应该是安全的。

创建一个像这样的函数:

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);

这应该执行您想要的操作 - 允许该特定程序的任何崩溃静静地消失。

然而,还有一点需要注意:任何时候引入第 3 方组件(DLL、OCX 等)时,都存在其中一个组件也可能调用 SetUnhandledExceptionFilter 并因此用自己的回调替换您的回调的风险。我曾经遇到过一个 ActiveX 控件,它在实例化时会设置自己的回调。更糟糕的是,它在被销毁时未能恢复原来的回调。这似乎是他们代码中的一个错误,但无论如何,我都必须采取额外的步骤来确保我想要的回调至少在他们的控制关闭后恢复。因此,如果您发现有时这似乎对您不起作用,即使您知道自己已经正确设置了回调,那么您可能会遇到类似的情况。

Hans Passant's answer about SetUnhandledExceptionFilter is on the right track. He also makes some good points about not being able to do too much within the callback because various parts of the process could be in an unstable state.

However, from the way the issue is described, it doesn't sound like you want to do anything except tell the system not to put up the normal crash dialog. In that case, it's easy and should be safe regardless of what parts of the process the crash may have affected.

Make a function something like this:

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;
}

And somewhere in your program (probably as early as possible) set the callback:

SetUnhandledExceptionFilter(UnhandledExceptionCallback);

That should do what you want - allow any crashes of that particular program to die silently.

However, there's something else to note about this: Any time you bring in 3rd-party components (DLLs, OCXs, etc) there is a risk that one of them may also call SetUnhandledExceptionFilter and thus replace your callback with their own. I once encountered an ActiveX control that would set its own callback when instantiated. And even worse, it failed to restore the original callback when it was destroyed. That seemed to be a bug in their code, but regardless I had to take extra steps to ensure that my desired callback was at least restored when it was supposed to be after their control was shutdown. So if you find this doesn't appear to work for you sometimes, even when you know you've set the callback correctly, then you may be encountering something similar.

心奴独伤 2024-09-19 16:04:48

在开发 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.

I found myself in exactly this situation while developing a Delphi application. I found that I needed two things to reliably suppress the "app has stopped working" dialog box.

Calling SetErrorMode(SEM_NOGPFAULTERRORBOX); suppresses the "app has stopped working" dialog box. But then Delphi's exception handler shows a message box with a runtime error message instead.

To suppress Delphi's exception handler I call SetUnhandledExceptionFilter with a custom handler that terminates the process by calling Halt.

So the skeleton for a Delphi client app that runs code prone to crashes becomes:

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.
霞映澄塘 2024-09-19 16:04:48

我完全不确定,但也许 SetErrorMode< code>SetThreadErrorMode 适合你吗?

I'm not at all sure, but perhaps SetErrorMode or SetThreadErrorMode will work for you?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文