Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows - Prevent crashes "Checking for a solution..." and "Restarting the program..."

Tags:

windows

crash

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.

like image 616
James Cadd Avatar asked Nov 08 '09 23:11

James Cadd


1 Answers

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.

like image 55
Heath Hunnicutt Avatar answered Oct 05 '22 18:10

Heath Hunnicutt