Работает консольное приложение. Функционал устраивает. Но одна вещь смущает. Хотелось бы корректно завершать приложение. Есть ли способ получить сообщение от системы, что нажат крестик или принудительно завершили? или только так ?: Код (Text): RegisterClassEx -> CreateWindow -> GetMessage
Тут кое-что с RSDN Код (Text): // crt_signal.c // compile with: /c // Use signal to attach a signal handler to the abort routine #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <tchar.h> void SignalHandler(int signal) { printf("Application aborting...\n"); } int main() { typedef void (*SignalHandlerPointer)(int); SignalHandlerPointer previousHandler; previousHandler = signal(SIGABRT, SignalHandler); abort(); }
The SetWinEventHook function sets an event hook function for a range of events. в качестве эвента EVENT_CONSOLE_END_APPLICATION (0x4007). И никаких CreateWindow
Хуки обычно в dll. Если подгружать свою, то можно. Код (Text): BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad){ switch (fdwReason){ case DLL_PROCESS_ATTACH: // DLL проецируется на адресное пространство процесса break; case DLL_THREAD_ATTACH: // создается поток break; case DLL_THREAD_DETACH: // поток корректно завершается break; case DLL PROCESS_DETACH // DLL отключается от адресного пространства процесса // Где-то здесь выполнится код при завершении. break; } return(TRUE); // используется только для DLL_PROCESS_ATTACH }
Чего-то этим кодом создалось неубиваемое приложение. Прийдется перезагружаться. Код (Text): #include <windows.h> #include <stdio.h> #include <stdlib.h> #include <signal.h> #include <tchar.h> WINEVENTPROC CALLBACK WinEventProc( HWINEVENTHOOK hWinEventHook, DWORD event, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime ){ printf("Application aborting...\n"); MessageBox(0,0,0,0); Sleep(5000); return 0; } int main(){ // Set up event call back HWINEVENTHOOK hEventHook = SetWinEventHook(EVENT_CONSOLE_END_APPLICATION, EVENT_CONSOLE_END_APPLICATION, NULL, // Use our own module (WINEVENTPROC) WinEventProc, // Our callback function (DWORD) GetCurrentProcess(), // All processes 0, // All threads 0); //WINEVENT_SKIPOWNPROCESS | //WINEVENT_OUTOFCONTEXT); Sleep(5000); }
Спасибо, Ezrah Код (Text): #include <windows.h> #include <stdio.h> #include <tchar.h> HANDLE hStopProgram_Command; BOOL WINAPI ConsoleHandler(DWORD CEvent){ switch(CEvent) { case CTRL_CLOSE_EVENT: printf("ConsoleHandler: EXIT\n"); break; // тут обработка остальных сигналов } SetEvent(hStopProgram_Command); while (true); return TRUE; } int main(int argc, char* argv[]){ DWORD dRes; hStopProgram_Command = CreateEvent(NULL, TRUE, FALSE, NULL); SetProcessShutdownParameters(0, SHUTDOWN_NORETRY); if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE) { // unable to install handler.display message to the user dRes = GetLastError(); printf("(MAIN): Unable to install handler! (err = %i)\n", dRes); return -1; } while (true) { dRes = WaitForSingleObject(hStopProgram_Command, 10000L); if (dRes != WAIT_ABANDONED) break; } printf("Stop_program signal handled! Press OK button in msg to terminate program...\n"); MessageBox(0,TEXT("Press OK!!!"), TEXT("Stopping"),0); return 0; } на сохранение параметров 5-ти секунд хватит
Ezrah Честно говоря, я был бы рад увидеть рабочий кошерный вариант. Особенно для случая, когда не хочется умирать вместе с консолью.
Добавление консольного хандлера через SetConsoleCtrlHandler на обработку CTRL_CLOSE_EVENT и есть кошерный вариант. В обработчике не надо смотреть другие сообщения (если не нужны), нужно обработать CTRL_CLOSE_EVENT и сразу же вернуть true. У ТС все зависло из-за его while (true); в обработчике.
Dmitry_Milk Если вернуть true, приложение сразу же завершится. Для false аналогично. Если не вернуть ничего, оно принудительно завершится через определённый таймаут в несколько секунд.
Нет. Не сразу. Несколько секунд дает. Проверено опытом. Если же вернуть false - тогда будет вызван следующий обработчик (если он не был удален из списка обработчиков) - и тогда, если это дефаултовый обработчик, он сразу же сделает ExitProcess.
И кстати еще - если за эти несколько секунд приложение так и не завершится самостоятельно - его также винда не завершит сразу принудительно, а выведет юзеру вопрос с предложением убить процесс.
Dmitry_Milk Во-первых, моим опытом проверено, что не даёт. Умирает моментально. Во-вторых, я не хочу умирать , несколько секунд мне недостаточно. Пусть даже консоль умрёт, а приложение останется жить. Не выведет. Уничтожит моментально. Даже если приложение под отладчиком, отаттачит и уничтожит.
Код (Text): #include <windows.h> #include <stdio.h> #include <conio.h> HANDLE hEvent; int __stdcall conHandler( DWORD dwCtrlType) { if(dwCtrlType==CTRL_CLOSE_EVENT ) { SetEvent(hEvent); return true; } return false; } void main() { puts("Starting"); hEvent=CreateEvent(NULL,FALSE,FALSE,NULL); SetConsoleCtrlHandler(conHandler,true); while(WaitForSingleObject(hEvent,1000)!=WAIT_OBJECT_0) { puts("more wait"); } puts("Stop requested. Press any key to stop."); getch(); puts("Stopping"); }
У меня это работает как запланировано - при нажатии на крестик пишет "Stop requested. Press any key to stop." и ждет нажатия клавиши, после нажатия пишет "Stopping" и закрывается. Если не успеваю в течение пары секунд нажать - вылезает только предложение прибить процесс, но само приложение продолжает вести себя так же, как и в первом случае. Windows XP. Может, зависит от политик по умолчанию? Еще надо бы глядеть на SetProcessShutdownParameters.