tags:

views:

370

answers:

5

This may not be a purely programming related question, but I come across this often during development. When my app crashes and I choose to kill it, Windows automatically throws up a "Checking for a solution..." dialog box. When I hit the cancel button on that I get another dialog box that says "Restarting the program..." Is there a way to prevent this behavior? When I stop an app I'd prefer if it were silently killed. I'm using Windows 7 if the platform is important.

+1  A: 

Follow the steps in this article to control this behavior.

Traveling Tech Guy
Great solution, removes WER for all apps.
James Cadd
A: 

Take a look at the Windows Error Reporting APIs.

Joey
+1  A: 

Check out the answers on these questions:

Luke Quinane
+1  A: 

Although Microsoft recommends using a newer replacement API available only on Windows Vista and later, there is an API which works for all versions of Windows from XP onward: AddERExcludedApplication(). This function takes the module name without path information (e.g., "myprogram.exe") for which error reporting is to be disabled.

The new method available only Windows Vista and later is to call WerAddExcludedApplication() function. This API allows you to specify whether it should change the HKEY_CURRENT_USER registry hive, or the HKEY_LOCAL_MACHINE registry hive. Be sure to set this for the HKCU if the HKLM set fails, such as:

typedef BOOL (*ADD_MER_EXCLUDED_APP_XP)  (PCWSTR);
typedef BOOL (*ADD_MER_EXCLUDED_APP_VISTA)  (PCWSTR, BOOL);

bool disable_microsoft_error_reporting(PCWSTR wz_app)
{
    const WCHAR * const WZ_MER_DLL_XP  = L"faultrep.dll";
    const char  * const SZ_MER_PROC_XP  = "AddERExcludedApplicationW";

    const WCHAR * const WZ_MER_DLL_VISTA = L"wer.dll";
    const char  * const SZ_MER_PROC_VISTA = "WerAddExcludedApplicationW";

    const int WER_EXCLUDE_FOR_ALL_USERS  = TRUE;
    const int WER_EXCLUDE_FOR_THIS_USER  = FALSE;

    HANDLE  hlib_error_reports_xp  = NULL;
    HANDLE  hlib_error_reports_vista = NULL;

    ADD_MER_EXCLUDED_APP_XP  add_mer_excluded_app_xp  = NULL;
    ADD_MER_EXCLUDED_APP_VISTA add_mer_excluded_app_vista = NULL;

    bool  success      = false;

    // First, attempt the API that has been around since XP.
    hlib_error_reports_xp = LoadLibrary(WZ_MER_DLL_XP);

    if (hlib_error_reports_xp)
    {
     add_mer_excluded_app_xp = (ADD_MER_EXCLUDED_APP_XP)GetProcAddress(hlib_error_reports_xp, SZ_MER_PROC_XP);

     if (add_mer_excluded_app_xp)
      success = add_mer_excluded_app_xp(wz_app);

     FreeLibrary(hlib_error_reports_xp);
     hlib_error_reports_xp = NULL;
     add_mer_excluded_app_xp = NULL;

     if (success)
      return true;
    }

    // That did not succeed.  Attempt the Vista API.
    hlib_error_reports_vista = LoadLibrary(WZ_MER_DLL_VISTA);

    if (hlib_error_reports_vista)
    {
     add_mer_excluded_app_vista = (ADD_MER_EXCLUDED_APP_VISTA)GetProcAddress(hlib_error_reports_vista, SZ_MER_PROC_VISTA);

     if (add_mer_excluded_app_vista)
     {
      success = (S_OK == add_mer_excluded_app_vista(wz_app, WER_EXCLUDE_FOR_ALL_USERS));

      if (!success)
       success = (S_OK == add_mer_excluded_app_vista(wz_app, WER_EXCLUDE_FOR_THIS_USER));
     } 

     FreeLibrary(hlib_error_reports_vista);
     hlib_error_reports_vista = NULL;
     add_mer_excluded_app_vista = NULL;

     if (success)
      return true;
    }

    // Nothing worked.  Fail.
    return false;
}

To further curtail the execution of the WER components, imeplement an unhandled exception filter and pass it to: SetUnhandledExceptionFilter() function. To shunt WER, your filter must never return EXCEPTION_CONTINUE_SEARCH or EXCEPTION_EXECUTE_HANDLER.

One of the drawbacks of implementing the SetUnhandledExceptionFilter() function is that it interferes with Just-in-time debugging.

You mention you want the app to be "silently killed." In that case:


LONG WINAPI global_exception_filter(struct _EXCEPTION_POINTERS *exception_info)
{
    ExitProcess(0xDEDD000D);
}


int WINAPI WinMain(
    HINSTANCE _hinstance,
    HINSTANCE hinstance_prev,
    LPSTR sz_cmd_line,
    int cmd_show
)
{
    SetUnhandledExceptionFilter(global_exception_filter);
    /* ... */
}

Will cause the application to immediately vanish upon unhandled exception. N.B., the exit code to return is a matter of taste.

Heath Hunnicutt
One HUGE caveat: Nobody should EVER use SetUnhandledExceptionFilter in production code.If you DO use SetUnhandledExceptionFilter, make sure that you call TerminateProcess in your exception filter - otherwise you're going to turn an easily debuggable crash into one of two things: If you're lucky, you get a subtle memory corruption that will cause no ends of trouble for your customers. If you're not lucky, you'll introduce an exploitable security bug in your application.
Larry Osterman
Actually, my thought was install a filter which calls FatalAppExit(). BTW, hi Larry!
Heath Hunnicutt
@Larry, for WerAddExcludedApplication(), do you know if that requires a module name rather than a complete path, or vice versa?
Heath Hunnicutt
@Heath: Unfortunately I do't know. Probably a full path if I had to guess.
Larry Osterman
Don't know why (and don't much care as its not used) but global_exception_filter wouldn't compile for me until I removed the name of the pointer, exception_info.
Tom
+1  A: 

I realize that others have answered with ways to work around this, but...

Let's not forget that the best way to protect against this is to write a program that doesn't crash. :-) You shouldn't be seeing this if you are using memory correctly and not hanging the GUI thread.

Altering the behavior of an application crash is a great way to introduce subtle and deadly bugs. See also this blog post from Microsoft's Raymond Chen.

asveikau
It's James Cadd's right to prevent Microsoft from spying on his code, regardless of whether his code crashes or some MS dll he calls crashes on 1% of customers' systems.
Heath Hunnicutt
I don't think they're spying on his code. All the crash reports get fed into their Winqual system where devs can see crash reports for their applications: http://en.wikipedia.org/wiki/Winqual
Luke Quinane
Yes, all devs who own certificates can see the reports for their own application. Where is it stated that Microsoft employees cannot look at the reports for 3rd-party applications? Don't search for that clause in the usage agreement -- it isn't there.
Heath Hunnicutt
To be honest, it's Visual Studio 2010 beta 2 that's doing a fair amount of crashing - I'll take some of the blame since it's my code running in the designer ;)
James Cadd