Как немедленно прекратить разбитое приложение?

У меня есть приложение, которое иногда вызывает исключения. И мне нужно перезапустить его, если он разбился. Но проблема в том, что у меня есть Windows 7 здесь, и когда приложение выходит из строя, Windows показывает мне приятное диалоговое окно с предложением закрыть приложение. Но само приложение все еще работает, пока я не нажму "Закрыть". Как избавиться от этого окна и немедленно закрыть приложение без каких-либо диалоговых окон?

Ответ 1

В идеале вы будете использовать все исключения в самой внешней области вашей программы. Однако иногда у вас нет такой возможности для внесения таких изменений, и диалоги сбоев не позволяют вам восстанавливаться после сбоя. В этих случаях вы можете отключить Отчеты об ошибках Windows, полностью или для конкретной программы.

В Windows 7: Пуск → Панель управления → Центр действий → Обслуживание → Проверка решений отчетов о проблемах → Настройки

Обновление: чтобы полностью отключить отображение отчетов об ошибках, измените параметр реестра DontShowUI:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Отчеты об ошибках Windows\DontShowUI

Ответ 2

Вы можете использовать концепцию Dr Watson для обнаружения сбоя и перезапуска приложения. Используйте следующее:

Установите таймер вроде:

SetTimer( eIsDwwin, 30000, NULL);

Это проверит процесс Dr Watson каждые 30 секунд в системном процессе, используя следующее:

void CMainFrame::OnTimer(UINT nIDEvent) {

    case eIsDwwin:
        HANDLE hndl = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
        DWORD dwsma = GetLastError();
        DWORD dwExitCode = 0;
        PROCESSENTRY32  procEntry={0};
        procEntry.dwSize = sizeof( PROCESSENTRY32 );
        Process32First(hndl,&procEntry);
        do {
            if(((!strcmpi(procEntry.szExeFile,"dwwin.exe"))|| 
                (!strcmpi(procEntry.szExeFile,"drwatson.exe"))||
                (!strcmpi(procEntry.szExeFile,"drwtsn32.exe"))||
                (!strcmpi(procEntry.szExeFile,"WerFault.exe"))) &&
                (procEntry.th32ParentProcessID == GetCurrentProcessId())) {

                WSACleanup();
                PostMessage( WM_CLOSE);
                Sleep(500);

        if(0==strcmpi(procEntry.szExeFile,"dwwin.exe")) {
            system("TASKKILL /IM dwwin.exe /F");
        } else if(0==strcmpi(procEntry.szExeFile,"drwatson.exe")) {
            system("TASKKILL /IM drwatson.exe /F");
        } else if(0==strcmpi(procEntry.szExeFile,"drwtsn32.exe")) {
            system("TASKKILL /IM drwtsn32.exe /F");
            } else if(0==strcmpi(procEntry.szExeFile,"WerFault.exe")) {
            system("TASKKILL /IM WerFault.exe /F");
        } else {
                    system("TASKKILL /IM WerFault.exe /F");
        }
                break;
        }
    } while(Process32Next(hndl,&procEntry));

        CloseHandle(hndl);
    break;
    }
}

Это закроет приложение, которое разбилось, изящно.

Анетом может быть использование API сигналов в Windows для обработки исключений и сбоев.

Ответ 3

Незнание языка вашего приложения делает его немного жестким, но вы обычно можете справиться с этим, запустив приложение в эквиваленте блока try/catch (как на С#, С++ или Python). В псевдо-Csharp-ish-коде:

bool done = false;
main()
{
    while( !done )
    {
        AppClass aclass = new AppClass();
        try
        {
            aclass->Run();
        }
        catch( Exception x )
        {
             LogErrorSomehow(x);
             delete aclass;
             continue;
        }
    }
}

По сути, лучший способ обойти ошибку "необработанного исключения" - обработать исключение, поймав его и предпринять соответствующие действия (даже если это действие ничего не делает).

В этом примере, если кто-то хочет закрыть ваше приложение, вы должны установить значение "done" в true и вернуться из Run().