2011-06-23 87 views
0

我已經編寫了一個窗口服務,它捕獲UDP消息,以用戶身份創建進程,通過命名管道將消息發送到進程並重復。服務在XP中效果很好,但在一次迭代之後在Windows 7中意外終止。事件查看器顯示,在將消息傳遞給該服務後,出現應用程序錯誤,然後意外終止了我的服務。應用程序錯誤說錯誤模塊是ntdll.dll。調試我的服務將顯示代碼停止的位置。Windows服務在Windows 7中意外終止

這是我的工作循環。在XP

do 
{ 
    DebugLog("Waiting For UDP message"); 
    if(recvfrom(socketId, buffer, buffSize, 0, &clientAddrCast, &size) >= 0) 
    { 
     DebugLog("Create Named Pipe"); 
     hPipe = CreateNamedPipe(lpszPipename,  // pipe name 
       PIPE_ACCESS_DUPLEX,  // read/write access 
       PIPE_TYPE_MESSAGE |  // message pipe 
       PIPE_READMODE_MESSAGE, // message read mode 
       1,      // maximum Instaces 
       buffSize,    // output buffer size 
       buffSize,    // input buffer size 
       5000,     // client time-out 
       &pSecAttrib);   // security attributes 

     if (hPipe == INVALID_HANDLE_VALUE) 
      ErrorLog("CreateNamedPipe"); 


     DebugLog("Create User Process"); 
     if(!CreateProcessAsUser(hTokenDupe, "C:\\Services\\UDPClient_UserApp.exe", NULL, NULL, NULL, false, dwCreationFlags, NULL, NULL, &si, &pi)) 
     { 

      // if client app fails use SendMessage as failsafe 
      //WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, sessionID, pTitle, sizeof(pTitle), 
       //buffer, sizeof(buffer), MB_OK, 30, &resp, false); 
       ErrorLog("CreateProcess"); 
     } 
     else 
     { 
      DebugLog("Writing to User Process"); 
      // Open pipe to client 
      if(cSuccess = ConnectNamedPipe(hPipe, NULL) == 0) 
       ErrorLog("ConnectNamedPipe"); 
      else 
      { 
       Sleep(2000); 

       cbToWrite = (lstrlen(buffer)+1)*sizeof(TCHAR); 

       if(!WriteFile( 
        hPipe,     // pipe handle 
        buffer,     // message 
        cbToWrite,    // message length 
        &cbWritten,    // bytes written 
        NULL))     // not overlapped 
        ErrorLog("WriteFile"); 
      } 
     } 

    } 

    DebugLog("Cleanup"); 
    DestroyEnvironmentBlock(&pEnv); 
    DisconnectNamedPipe(hPipe); 
    CloseHandle(hPipe); 
    ErrorLog("test");  

}while(gServiceStatus.dwCurrentState == SERVICE_RUNNING); 

我的調試日誌顯示DebugLog("Cleanup")後循環回DebugLog("Waiting For UDP message")。在Windows 7中,它在DebugLog("Cleanup")之後停止。我正在調查我的代碼可能會產生的問題。任何其他建議將不勝感激。

感謝, 約瑟夫G.

+0

對不起。在調用DebugLog(「Cleanup」)之後它會失敗。我已經編輯過我的帖子。 –

回答

0

我的猜測是在Win7更嚴格的安全是得到自己。

這裏有缺少的代碼,例如pSecAttrib是什麼?加強你的錯誤處理(例如)如果管道創建失敗,你不會執行循環體的其餘部分,並且你確切地知道哪個API失敗以及原因。

CreateProcessAsUser - 您將哪些用戶作爲服務運行?該用戶是否擁有正確的權限 - 它們在Win7和WinXP上可能會有所不同。

日誌GetLastError()值後全部 Win32失敗。讓自己的生活更輕鬆一點,這可能會在某一天在遠程站點進行製作,那麼您將如何排除故障?

那是什麼Sleep(2000);?可疑。如果管道是開放的,爲什麼不只是發送數據並避免這種延遲。命名管道服務器代碼是否緩慢以在管道上發佈讀取請求?

+0

'pSecAttrib'獲取活動用戶安全屬性。 'CreateProcessAsUser'設置爲以活動用戶身份運行。 –

+0

'GetLastErrot'在所有'ErrorLog'函數中被調用。 「睡眠(2000)」在那裏,因爲服務創建的進程需要很長時間才能打開其結束。它可能不需要整整2秒鐘。這個數字被任意地放置在那裏。 –

+0

很高興聽到您記錄錯誤。我對DestroyEnvironmentBlock的調用感到好奇。這是在循環內,但我沒有看到循環內的init。這可能是一個錯誤,雖然我認爲這會失敗,而不是第一次(除非你根本不初始'pEnv'?)。難道你不能通過在調試器中運行這個調用堆棧來獲得正確的調用堆棧,直到你遇到異常?你應該能夠比「清理日誌之後」做得更好,縮小這個範圍。另外,請檢查**所有** Win32 API調用是否有錯誤。如果一個人失敗了,並且你錯過了這個事實,那麼進一步的行爲可能是意想不到的 –