Консоль WM_DESTROY

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

  1. paralvic

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

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

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

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

    Публикаций:
    0
    Тут кое-что с 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
    The SetWinEventHook function sets an event hook function for a range of events.

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

    Ezrah Member

    Публикаций:
    0
    SetConsoleCtrlHandler для этих целей используется.
     
  5. paralvic

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

    Публикаций:
    0
    Хуки обычно в 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
    Чего-то этим кодом создалось неубиваемое приложение.
    Прийдется перезагружаться.

    Код (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
    Спасибо, 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
    В результате сделал длл. Другие способы в хр приводят к зависанию программы.
     
  9. Ezrah

    Ezrah Member

    Публикаций:
    0
    Так люди становятся индусами...
     
  10. l_inc

    l_inc New Member

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

    Dmitry_Milk Member

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

    l_inc New Member

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

    Ezrah Member

    Публикаций:
    0
    Откуда инфа?
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Ezrah
    Из опыта.
     
  15. Dmitry_Milk

    Dmitry_Milk Member

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

    Dmitry_Milk Member

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

    l_inc New Member

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

    Dmitry_Milk Member

    Публикаций:
    0
    Код (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
    Dmitry_Milk
    Ну и что Вы этим хотели показать? Умирает моментально при закрытии консоли.
     
  20. Dmitry_Milk

    Dmitry_Milk Member

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