How do I prevent a child process from displaying the Windows Error Reporting dialog?


A customer wanted to know if there was a way to disable Windows Error Reporting for a child process. Their scenario was that they had a main program which runs a child program that is expected to crash (because it's a unit test). Normally, this would result in the Windows Error Report dialog appearing, offering to send a crash report to Microsoft. This dialog is unwanted, since it makes it difficult to run the unit test as part of an automated script, plus there's no point sending crash reports for a unit test that is expected to crash.

One person suggested using the Wer­Add­Excluded­Application function to add the program to the list of programs to be excluded from error reporting, and then call the Wer­Remove­Excluded­Application function when the test completes. There are some problems with this approach:

  • The name of your unit test application may happen to match that of a legitimate application, and the Wer­Add­Excluded­Application function takes only the file name, not a full path. You can try to arrange for your unit test name to be sufficiently unique that this sort of collision is unlikely.

  • If the test harness crashes, then Wer­Remove­Excluded­Application will never get called, and then the unit test ends up excluded permanently.

  • Suppose two copies of the unit test are running. Given that you're doing automated testing, there's a decent chance that this will happen; for example, the automated system may be running unit tests as part of a gated check-in system, and multiple check-ins could be undergoing validation at once. In that case, both test harnesses will call Wer­Add­Excluded­Application when they start up, and the first one to finish will call Wer­Remove­Excluded­Application. This rips the registration out from under the second instance, which is still running, and the crash dialog will appear.

Basically, we are applying a global solution to a local problem.

Better to apply a local solution: Since the error mode is inherited by child processes, you can have the test harness call Set­Error­Mode with the SEM_NO­GP­FAULT­ERROR­BOX flag to disable the error reporting dialog for itself and its children.

Here's a Little Program to illustrate. Remember that Little Programs do little to no error checking. In this case, the Little Program also leaks handles!

#include <windows.h>
#include <stdio.h>

int main(int argc, char**argv)
{
    printf("Error mode is %d\n", GetErrorMode());
    if (argc == 1) {
        TCHAR buf[256];
        GetModuleFileName(nullptr, buf, 256);
        STARTUPINFO si = { sizeof(si) };
        PROCESS_INFORMATION pi;
        SetErrorMode(SEM_NOGPFAULTERRORBOX);
        printf("Spwaning child, error mode is %d\n", GetErrorMode());
        CreateProcess(buf, TEXT("a b c d"), nullptr, nullptr, FALSE,
            0, nullptr, nullptr, &si, &pi);
        WaitForSingleObject(pi.hProcess, INFINITE);
        printf("Done\n");
    } else {
        DebugBreak();
    }
    return 0;
}

If you run this program, it will start by reporting that its error mode is zero, and then it changes to 2 (which is the value of the SEM_NO­GP­FAULT­ERROR­BOX flag), and then the child process will report that its error mode is 2 (inherited), and then it will crash by invoking a nonexistent debugger. Since error dialogs are disabled, the child process will exit silently.

Comments (25)
  1. Mason Wheeler says:

    What I've never understood is, why is that there by default anyway? If I have a bug in my code, and I publish it, and someone uses it and it crashes on their system, what can *Microsoft* do with the debug information from my crashed program?

    If they could forward it on to me, that would be useful, but then again, pretty much any developer with the skills to know what to do with a crash report is going to build an automated crash reporting feature into their own program anyway, one that's going to gather more domain-specific information than a generic Windows crash dump, so what good does it do me to register with Microsoft for something like that? And if I don't register with Microsoft, why is this feature that does me no good pestering my users?

    1. Just because the crash is in your app doesn't mean the bug is in your app. Often, apps expose bugs in Windows.

    2. BZ says:

      I think they *do* forward crash reports to developers. Isn't there some sort of program you can opt in to for this?

      1. Was. No more. Microsoft said "shoo, developers!" after Windows 8.

        I don't know about Metro-style apps though. There could be a program for them.

      2. They do. If you sign your binary, you can get all WER crash reports related to it right to you. That's how we catch and fix many issues, which would normally go unreported.

    3. Adrian says:

      There are drawbacks to embedding your own crash reporting into your program. The main one is that it's the crash reporting is best done from an external process. Having a process try to report its own crashes can be problematic because the state of the process is uncertain; it may fail to send a report for some kinds of crashes.

      So, to do your own crash reporting, you should install a service or otherwise spin up a watchdog process.

      But, as a user, I'd much prefer it if all of the apps I run could share such a single crash-reporting service rather than having one per application (or, if you're lucky, one per vendor). WER makes that possible. Software vendors can get access to dumps of their collected by WER if they register with Microsoft and meet certain quality bars.

      1. Firefox and Chrome report their own crashes without installing a service or having a watchdog process. crashreporter.exe runs every time after the crash. AVG products do the same thing.

        My people have been pressuring me to avoid sending any crash data to Microsoft after this whole privacy sensation surrounding Microsoft, although I did nothing about it.

        1. Adrian says:

          Google Chrome relies on GoogleCrashHandler.exe, of which there are 32-bit and 64-bit versions. On my machine, they are set to run all the time unless you turn off the telemetry option in Chrome. The processes are small and lightweight, so it's not a big deal.

          But if every application or vendor required and extra process or two, it could add up.

          1. Because it sends usage statistics too, not because crash handling needs it running all the times.

      2. Tim! says:

        Last time I tried to get useful data from WER (through the winqual site) the processing queue was at least a week long. A week is too long to wait. Then you have to actively get on the winqual site to browse the results. Rolling your own allows for immediate feedback, notification, and customized bucketing.

        1. Henri Hein says:

          Interesting. The only case when I would have wanted crash reports within a week is if I'm sharing an alpha release in-house or to a particularly close partner or customer. In those cases, if the users see any crashes, I can get the DMP files directly from them.

          The WER program is useful to get data from the full corpus of your user-base. For instance, how many users are still using an old version known to be unstable? Or, say the program becomes unstable only after weeks of continuous usage on a system used for other many things. In those cases, a week is not really a useful timeframe.

          1. Tim! says:

            This was for a small MMOG: a highly complex codebase with relatively frequent updates and a test team insufficient to cover all possible user scenarios and edge cases.

    4. Henri Hein says:

      Microsoft does indeed make crash reports available to developers, and it's an outstanding program. It's really easy to set it up, and it gives me visibility into what crashes users are seeing. It tells me how often my program crashes 'in the wild,' what the biggest source of crashes are, and where exactly in the code those crashes occur. (It's also a great feeling when I see that pretty much all the crashes are in third-party code...)

  2. BZ says:

    What I want to know is when would a crash be an expected outcome in a unit test? Unit tests are modeling real life situations. Is crashing in a real life scenario ever the right thing to do (yes, I know you shouldn't attempt to stop a crash in progress, but that's when it's already in progress)? And if you don't control the child process and it crashes under certain circumstances, why would you want to test for this? Would something be wrong if the child process unexpectedly *didn't* crash?

    1. Joshua says:

      To test the crash handlers of course.

    2. Nathan says:

      I think you are confusing expectation with something that happens every time.

      9 times out of 10 the test units expose bugs, but hopefully most of the time it will actually function correctly. But in cases it doesn't you do not want to clutter the screen with lots of useless dialogs

    3. You might want to verify that the component correctly detects an invalid condition (e.g., buffer overrun), and the component is designed so that invalid conditions crash the process.

  3. DoomMuffins says:

    This is still a global solution to a local problem, only it's global to the parent process rather than the entire system. A different thread in the parent process may suffer the side effects, just as it would if you were modifying your own environment variables so that a child process you're going to create might inherit them. In the case of the environment variables there's a correct solution in the form of the relevant parameter to CreateProcess. In the case of the error mode, there isn't (as far as I know).

    1. True, but it's less global than the machine-global solution. The purely local solution would be for the unit test itself to make the SetErrorMode call.

      1. DoomMuffins says:

        That assumes you have control over the code of the executable you're running (or at least some part of it), otherwise the only robust solution would be having a sacrificial process do your bidding.

    2. skSdnW says:

      Win7 added SetThreadErrorMode but I assume CreateProcess inherits the process value?

  4. Zack says:

    I'm wondering if there is any way to turn off error dialogs _but_ also cause the information that would have appeared in the error dialog to get logged somewhere a monitoring program can pick it up. For example, again in the context of a test suite: you don't want the program being tested to pop up a dialog box if it can't find all of its required DLLs, but you probably _do_ want to log the name of the missing DLL. SEM_FAILCRITICALERRORS turns off the dialog box in this case, but as far as I can tell, the dialog box is the only place the missing DLL's name is reported...

  5. skSdnW says:

    For anyone actually doing this in their own program that is more complex than this example, it is important to call SetErrorMode twice like Raymond does in a previous post about this topic: https://blogs.msdn.microsoft.com/oldnewthing/20040727-00/?p=38323/

  6. Brian Nixon says:

    Is there a way to prevent WER being triggered by exceptions raised in TLS callbacks? In Windows 7 these are silently swallowed by the operating system but in Windows 8.1 and Windows 10 they trigger WER (even though the process is allowed to continue running). Setting the error mode can prevent WER from saving crash dumps and writing event log entries, but it doesn’t avoid a service host process and WerFault.exe being started each time. When this happens for each of the 30+ threads the app creates, it leads to a noticeable slow-down in the running of the program.

  7. alegr1 says:

    Now if only VisualStudio were so smart to disable Windows crash and compatibility assist dialogs for the processes being debugged.

Comments are closed.

Skip to main content