Консоль WM_DESTROY

Тема в разделе "WASM.BEGINNERS", создана пользователем paralvic, 3 фев 2012.

  1. paralvic

    paralvic Пархоменко Александр Викторович

    Публикаций:
    0
    Регистрация:
    20 ноя 2010
    Сообщения:
    294
    Адрес:
    Нижний Новгород
    Работает консольное приложение. Функционал устраивает.
    Но одна вещь смущает. Хотелось бы корректно завершать приложение.

    Есть ли способ получить сообщение от системы, что нажат крестик или принудительно завершили?
    или только так ?:
    Код (Text):
    1. RegisterClassEx -> CreateWindow -> GetMessage
     
  2. paralvic

    paralvic Пархоменко Александр Викторович

    Публикаций:
    0
    Регистрация:
    20 ноя 2010
    Сообщения:
    294
    Адрес:
    Нижний Новгород
    Тут кое-что с RSDN
    Код (Text):
    1. // crt_signal.c
    2.   // compile with: /c
    3.   // Use signal to attach a signal handler to the abort routine
    4.   #include <stdio.h>
    5.   #include <stdlib.h>
    6.   #include <signal.h>
    7.   #include <tchar.h>
    8.  
    9.   void SignalHandler(int signal)
    10.   {
    11.       printf("Application aborting...\n");
    12.   }
    13.  
    14.   int main()
    15.   {
    16.       typedef void (*SignalHandlerPointer)(int);
    17.  
    18.       SignalHandlerPointer previousHandler;
    19.       previousHandler = signal(SIGABRT, SignalHandler);
    20.      
    21.       abort();
    22.   }
     
  3. FatMoon

    FatMoon New Member

    Публикаций:
    0
    Регистрация:
    28 ноя 2002
    Сообщения:
    954
    Адрес:
    Russia
    The SetWinEventHook function sets an event hook function for a range of events.

    в качестве эвента EVENT_CONSOLE_END_APPLICATION (0x4007). И никаких CreateWindow
     
  4. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    SetConsoleCtrlHandler для этих целей используется.
     
  5. paralvic

    paralvic Пархоменко Александр Викторович

    Публикаций:
    0
    Регистрация:
    20 ноя 2010
    Сообщения:
    294
    Адрес:
    Нижний Новгород
    Хуки обычно в dll. Если подгружать свою, то можно.
    Код (Text):
    1.     BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, PVOID fImpLoad){
    2.         switch (fdwReason){
    3.             case DLL_PROCESS_ATTACH:  // DLL проецируется на адресное пространство процесса
    4.                 break;
    5.             case DLL_THREAD_ATTACH: // создается поток
    6.                 break;
    7.             case DLL_THREAD_DETACH:  // поток корректно завершается
    8.                 break;
    9.             case DLL PROCESS_DETACH  // DLL отключается от адресного пространства процесса
    10.  
    11. // Где-то здесь выполнится код при завершении.
    12.  
    13.                 break;
    14.         }
    15.         return(TRUE);  // используется только для DLL_PROCESS_ATTACH
    16.     }
     
  6. paralvic

    paralvic Пархоменко Александр Викторович

    Публикаций:
    0
    Регистрация:
    20 ноя 2010
    Сообщения:
    294
    Адрес:
    Нижний Новгород
    Чего-то этим кодом создалось неубиваемое приложение.
    Прийдется перезагружаться.

    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. #include <stdlib.h>
    4. #include <signal.h>
    5. #include <tchar.h>
    6.   WINEVENTPROC CALLBACK WinEventProc( HWINEVENTHOOK
    7.       hWinEventHook, DWORD event, HWND hwnd,
    8.                   LONG idObject, LONG idChild,
    9.                   DWORD dwEventThread, DWORD dwmsEventTime ){
    10.       printf("Application aborting...\n");
    11.       MessageBox(0,0,0,0);
    12.       Sleep(5000);
    13.       return 0;
    14.   }
    15.   int main(){
    16.         // Set up event call back
    17.     HWINEVENTHOOK hEventHook = SetWinEventHook(EVENT_CONSOLE_END_APPLICATION,
    18.                                  EVENT_CONSOLE_END_APPLICATION,    
    19.                                  NULL,         // Use our own module
    20.                                  (WINEVENTPROC) WinEventProc, // Our callback function
    21.                                  (DWORD) GetCurrentProcess(),            // All processes
    22.                                  0,            // All threads
    23.                                  0);
    24.                                  //WINEVENT_SKIPOWNPROCESS |
    25.                                  //WINEVENT_OUTOFCONTEXT);  
    26.       Sleep(5000);
    27.   }
     
  7. paralvic

    paralvic Пархоменко Александр Викторович

    Публикаций:
    0
    Регистрация:
    20 ноя 2010
    Сообщения:
    294
    Адрес:
    Нижний Новгород
    Спасибо, Ezrah
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. #include <tchar.h>
    4. HANDLE hStopProgram_Command;
    5. BOOL WINAPI ConsoleHandler(DWORD CEvent){
    6.   switch(CEvent) {
    7.     case CTRL_CLOSE_EVENT:
    8.       printf("ConsoleHandler: EXIT\n");
    9.       break;
    10.     // тут обработка остальных сигналов
    11.   }
    12.   SetEvent(hStopProgram_Command);
    13.   while (true);
    14.   return TRUE;
    15. }
    16. int main(int argc, char* argv[]){
    17.   DWORD dRes;
    18.   hStopProgram_Command = CreateEvent(NULL, TRUE, FALSE, NULL);
    19.   SetProcessShutdownParameters(0, SHUTDOWN_NORETRY);
    20.   if (SetConsoleCtrlHandler((PHANDLER_ROUTINE)ConsoleHandler,TRUE)==FALSE) {
    21.     // unable to install handler.display message to the user
    22.     dRes = GetLastError();
    23.     printf("(MAIN): Unable to install handler! (err = %i)\n", dRes);
    24.     return -1;
    25.   }
    26.   while (true) {
    27.     dRes = WaitForSingleObject(hStopProgram_Command, 10000L);
    28.     if (dRes != WAIT_ABANDONED) break;
    29.   }
    30.   printf("Stop_program signal handled! Press OK button in msg to terminate program...\n");
    31.   MessageBox(0,TEXT("Press OK!!!"), TEXT("Stopping"),0);
    32.   return 0;
    33. }
    на сохранение параметров 5-ти секунд хватит
     
  8. paralvic

    paralvic Пархоменко Александр Викторович

    Публикаций:
    0
    Регистрация:
    20 ноя 2010
    Сообщения:
    294
    Адрес:
    Нижний Новгород
    В результате сделал длл. Другие способы в хр приводят к зависанию программы.
     
  9. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Так люди становятся индусами...
     
  10. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Ezrah
    Честно говоря, я был бы рад увидеть рабочий кошерный вариант. Особенно для случая, когда не хочется умирать вместе с консолью.
     
  11. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Добавление консольного хандлера через SetConsoleCtrlHandler на обработку CTRL_CLOSE_EVENT и есть кошерный вариант. В обработчике не надо смотреть другие сообщения (если не нужны), нужно обработать CTRL_CLOSE_EVENT и сразу же вернуть true. У ТС все зависло из-за его while (true); в обработчике.
     
  12. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Dmitry_Milk
    Если вернуть true, приложение сразу же завершится. Для false аналогично. Если не вернуть ничего, оно принудительно завершится через определённый таймаут в несколько секунд.
     
  13. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    Откуда инфа?
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Ezrah
    Из опыта.
     
  15. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Нет. Не сразу. Несколько секунд дает. Проверено опытом. Если же вернуть false - тогда будет вызван следующий обработчик (если он не был удален из списка обработчиков) - и тогда, если это дефаултовый обработчик, он сразу же сделает ExitProcess.
     
  16. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    И кстати еще - если за эти несколько секунд приложение так и не завершится самостоятельно - его также винда не завершит сразу принудительно, а выведет юзеру вопрос с предложением убить процесс.
     
  17. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Dmitry_Milk
    Во-первых, моим опытом проверено, что не даёт. Умирает моментально. Во-вторых, я не хочу умирать :), несколько секунд мне недостаточно. Пусть даже консоль умрёт, а приложение останется жить.
    Не выведет. Уничтожит моментально. Даже если приложение под отладчиком, отаттачит и уничтожит.
     
  18. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    Код (Text):
    1. #include <windows.h>
    2. #include <stdio.h>
    3. #include <conio.h>
    4.  
    5. HANDLE hEvent;
    6.  
    7. int __stdcall conHandler( DWORD dwCtrlType)
    8. {
    9.   if(dwCtrlType==CTRL_CLOSE_EVENT   )
    10.   {
    11.     SetEvent(hEvent);
    12.     return true;
    13.   }
    14.   return false;
    15. }
    16.  
    17.  
    18. void main()
    19. {
    20.   puts("Starting");
    21.   hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
    22.   SetConsoleCtrlHandler(conHandler,true);
    23.   while(WaitForSingleObject(hEvent,1000)!=WAIT_OBJECT_0)
    24.   {
    25.     puts("more wait");
    26.   }
    27.   puts("Stop requested. Press any key to stop.");
    28.   getch();
    29.   puts("Stopping");
    30. }
     
  19. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Dmitry_Milk
    Ну и что Вы этим хотели показать? Умирает моментально при закрытии консоли.
     
  20. Dmitry_Milk

    Dmitry_Milk Member

    Публикаций:
    0
    Регистрация:
    20 ноя 2007
    Сообщения:
    535
    У меня это работает как запланировано - при нажатии на крестик пишет "Stop requested. Press any key to stop." и ждет нажатия клавиши, после нажатия пишет "Stopping" и закрывается. Если не успеваю в течение пары секунд нажать - вылезает только предложение прибить процесс, но само приложение продолжает вести себя так же, как и в первом случае.
    Windows XP. Может, зависит от политик по умолчанию? Еще надо бы глядеть на SetProcessShutdownParameters.