2012-01-06 168 views
5

我有一個應用程序,當Windows關閉(或用戶註銷)時,我想優雅地關閉該應用程序。這曾經工作(在XP中),但在去年的某個時候它打破了,沒有人注意到。在Windows 7下它也破碎了(但不同)。當Windows關閉時,優雅的應用程序關閉

我們的產品有一個啓動許多其他進程的主進程(server.exe)。正常的關閉會讓server.exe詢問它開始關閉的所有進程。但是,當我調試此代碼時,似乎其他進程已被終止。我們的主進程(server.exe)是處理WM_QUERYENDSESSION和WM_ENDSESSION消息的唯一進程。下面的代碼(這個曾經在XP下工作,但沒有任何更多):

LRESULT CALLBACK master_wnd_proc 
(
    HWND hwnd,  /* (in) handle to window */ 
    UINT uMsg,  /* (in) message identifier */ 
    WPARAM wParam, /* (in) first message parameter */ 
    LPARAM lParam /* (in) second message parameter */ 
) 
{ 
    LRESULT result; /* return value */ 
    long msg_code; 

    switch (uMsg) 
    { 
     case WM_ENDSESSION: 
     if (wParam) 
     { 
      msg_code = PCS_WINDOWS_SHUTDOWN; 
      if(lParam & 0x01L) 
       msg_code = WINDOWS_SHUT_CLOSE; 
      if(lParam & 0x40000000L) 
       msg_code = WINDOWS_SHUT_CRIT; 
      if((unsigned long)lParam & 0x80000000) 
       msg_code = WINDOWS_SHUT_LOGOFF; 
      MsgGenerate(msg_code, MSG_SEVERE, MSG_LOG, ""); 

      ipc_declare_shutdown(msg_code); 

      //We need one more message in the message queue 
      //to force the message loop, below, to exit. 
      PostQuitMessage(EXIT_SUCCESS); 

      /* WARNING: Don't call MsgGenerate() after this point! */ 
     } 
     result = 0; 
     break; 

     case WM_QUERYENDSESSION: 

     /* return TRUE to say "okay to shutdown" 
      * If FALSE is returned, then other processes are not stopped 
      * and the session isn't ended. 
      */ 
     result = TRUE; 
     break; 

     /* for a Windows TIMER or for an IPC prompt, handle 
     * the old server code and tcall messages and 
     * once-per-second work. Notice that the 
     * once-per-second work could just be done on the WM_TIMER 
     * and the tcall work could just be done on the WM_APP_IPC_POSTED 
     * but I've merged them together here. The merge isn't 
     * necessary to fix a bug or anything, but rather to 
     * make the code more robust in the face of unexpected 
     * conditions. 
     */ 
     case WM_TIMER: 
     case WM_APP_IPC_POSTED: 
     /* now handle tcall messages */ 
     (void) server(); 

     result = FALSE; 
     break; 

     default: 
     result = DefWindowProc (hwnd, uMsg, wParam, lParam); 
     break; 
    } 

    return result; 
} 

這好像我們已經在過去的一年改爲東西將要求所有的子進程來處理WM_QUERYENDSESSION消息(我真的想避免這一點)。我似乎無法找到有關進程何時或沒有收到此消息的任何信息。

我已經使用新的API在Windows 7下工作,但想弄清楚爲什麼它在XP下破解,所以我可以有一個適用於這兩個操作系統的解決方案。

任何幫助?

+1

難道只是因爲某些原因,Windows以不同的順序關閉進程?有什麼可以保證你的'server.exe'是Windows關閉的第一件事情? – 2012-01-06 16:06:44

+0

在源代碼控制中你有這麼點代碼的可能性嗎?你至少可以看到它在去年是否發生了變化? – 2012-01-06 16:14:15

+0

不知道是什麼使得server.exe在其他人之前關機...... – 2012-01-06 17:30:16

回答

3

事情圍繞Vista時代發生了變化,不太確定這將如何影響您的代碼。最好的辦法就是不要讓Windows確定關機順序。只是要求它讓你的服務器在輔助進程之前得到關機通知:

DWORD dwLevel, dwFlags; 
    BOOL fOkay = GetProcessShutdownParameters(&dwLevel, &dwFlags); 
    ASSERT(fOkay); 
    if (fOkay && dwLevel > 0x100) { 
     fOkay = SetProcessShutdownParameters(dwLevel + 1, SHUTDOWN_NORETRY); 
     ASSERT(fOkay); 
    } 
+0

這幾乎可以... – 2012-01-06 17:11:24

+0

在XP下,這個工程很好。在Windows 7下,行爲仍然相同。 – 2012-01-06 17:12:27

+0

我知道這適用於Win7。別的東西讓你煩惱,很難猜到。 – 2012-01-06 17:21:01