У меня есть приложение, которое иногда вызывает исключения. И мне нужно перезапустить его, если он разбился. Но проблема в том, что у меня есть 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().