2012-01-06 8 views
5

Windows를 종료하거나 사용자가 로그 오프 할 때 정상적으로 종료하고 싶은 응용 프로그램이 있습니다. 이것은 (xp에서) 작동하지만 예기치 않은 사람들이 눈치 채지 못한 지난 해에는 언젠가 파산했습니다. Windows 7에서도 파손되었습니다 (0123).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에서 손상된 이유를 알고 싶습니다. 그래서 두 OS 모두에서 작동하는 솔루션을 가질 수 있습니다.

어떤 도움이 필요합니까?

+1

어떤 이유로 Windows가 다른 순서로 프로세스를 종료 할 수 있습니까? 'server.exe '가 Windows가 종료되는 첫 번째 것을 보장하는 것은 무엇입니까? –

+0

소스 제어에이 코드가있을 가능성이 있습니까? 작년에 그 변화가 있었는지 적어도 알 수 있었습니까? –

+0

다른 사람보다 먼저 server.exe를 종료하는 것이 확실하지 않은 이유는 무엇입니까? –

답변

3

비스타 시간이 바뀌었지만 코드에 어떤 영향을 미칠지 잘 모르겠습니다. 가장 좋은 방법은 종료 순서를 결정하기 위해 Windows에 남겨 두지 않는 것입니다. 도우미 프로세스가 시작되기 전에 서버에 종료 알림을 보내달라고 요청하십시오.

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

이것은 거의 작동합니다 ... –

+0

XP에서 이것은 위대한 작품. Windows 7에서의 동작은 여전히 ​​동일합니다. –

+0

나는 이것이 Win7에서 작동한다는 것을 알고있다. 뭔가 당신을 괴롭 히고 추측하기가 어렵습니다. –

관련 문제