代码之家  ›  专栏  ›  技术社区  ›  Elan

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

  •  6
  • Elan  · 技术社区  · 16 年前

    我们有一个非托管C++应用程序,它利用第三方API来读取CAD文件。在某些损坏的CAD文件上,第三方库崩溃并将我们的EXE文件带下来。因此,我们的主应用程序是一个单独的EXE,这样它就不会受到崩溃的影响。无论如何,我们最终会遇到恼人的微软错误报告对话框。

    我不想在系统范围内禁用Microsoft错误报告。有没有一种方法可以关闭单个应用程序的错误报告,这样如果它崩溃了,它就会在没有错误弹出对话框的情况下悄无声息地崩溃?

    5 回复  |  直到 16 年前
        1
  •  5
  •   mdb    16 年前

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

    但是,因为WER只会处理未处理的应用程序异常,所以应该可以通过向EXE添加“catch all”异常处理程序来禁止它。见 vectored exception handling 关于如何做到这一点的一些想法。

    请注意,抑制所有未处理的异常通常是一个坏主意(例如,会导致你的应用程序无法通过Windows徽标认证),因此你不应该不分青红皂白地使用此技术。。。

        2
  •  5
  •   Hans Passant    16 年前

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

    实际上,在回调中做些什么是充满麻烦的。这个程序死的时候,总是伴随着像AccessViolation异常这样的讨厌的事情。经常被堆损坏绊倒。当堆被烤熟时,尝试显示一个消息框让用户知道是很麻烦的。死锁也总是潜伏在角落里,随时准备在没有任何诊断的情况下锁定程序。

    唯一安全的方法是有一个守护主进程的助手进程。通过在回调中发送命名事件来唤醒它。为它提供内存映射文件所需的异常信息。当助手看到事件发出信号时,它几乎可以做任何它想要做的事情。包括显示一条信息,带一个小型垃圾场。终止主进程。

    这正是微软的WerFault助手的工作原理。

        3
  •  5
  •   TheUndeadFish    16 年前

    汉斯·帕桑关于 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);
    

    这应该做你想做的-允许任何特定程序的崩溃安静地死去。

    不过,还有一点需要注意:每当您引入第三方组件(dll、OCXs等)时,其中一个组件也可能调用SetUnhandledExceptionFilter,从而用它们自己的回调替换您的回调。我曾经遇到一个ActiveX控件,它在实例化时会设置自己的回调。更糟糕的是,它在被销毁时无法恢复原始回调。这似乎是他们代码中的一个bug,但不管怎样,我必须采取额外的步骤来确保我所需的回调至少在他们的控件关闭后恢复。因此,如果您发现这有时似乎对您不起作用,即使您知道已正确设置回调,那么您可能会遇到类似的情况。

        4
  •  2
  •   Jan Goyvaerts    15 年前

    在开发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.
    
        5
  •  0
  •   Jerry Coffin    16 年前

    我一点也不确定,但也许 SetErrorMode SetThreadErrorMode 会为你工作吗?

    推荐文章