2011-06-23 3 views
0

J'ai écrit un service Windows qui attrape un message UDP, crée un processus en tant qu'utilisateur, envoie le message au processus via des canaux nommés et répète. Service fonctionne très bien dans XP mais se termine de façon inattendue dans Windows 7 après une itération. L'Observateur d'événements montre qu'après avoir transmis mon message au service, il y a une erreur d'application suivie de la fin inattendue de mon service. L'erreur d'application indique que le module d'erreur est ntdll.dll. Le débogage de mon service montre où le code s'arrête.Le service Windows se termine de manière inattendue dans Windows 7

Voici ma boucle de travail.

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); 

Mes journaux de débogage dans XP montrent que, après DebugLog("Cleanup") il revient en boucle à DebugLog("Waiting For UDP message"). Dans Windows 7, il s'arrête après DebugLog("Cleanup"). Je suis à la recherche de problèmes que mon code pourrait créer. Toute autre suggestion serait la bienvenue.

Merci, Joseph G.

+0

Désolé pour ça. Il échoue quelque part après que 'DebugLog (" Cleanup ")' est appelé. J'ai déjà édité mon post. –

Répondre

0

Je pense serait une sécurité renforcée dans Win7 est vous obtiennent.

Il manque du code ici, par exemple, dans pSecAttrib? Augmentez votre gestion des erreurs de sorte que (par exemple) vous n'exécutez pas le reste du corps de la boucle si la création du tuyau échoue, et vous savez exactement quelle API a échoué et pourquoi.

CreateProcessAsUser - quel utilisateur utilisez-vous en tant que service? Cet utilisateur a-t-il les bonnes permissions? Il peut être différent sur Win7 et WinXP.

Valeur du journal GetLastError() après tous Echecs Win32. Facilitez-vous la vie, cela pourrait être dans la production dans un site distant un jour et comment allez-vous résoudre le problème?

Qu'est-ce que Sleep(2000); pour? Méfiant. Si le tuyau est ouvert, pourquoi ne pas simplement envoyer les données et éviter ce délai. Le code du serveur de canal nommé est-il si lent à publier une demande de lecture sur le canal?

+0

'pSecAttrib' obtient les attributs de sécurité des utilisateurs actifs. 'CreateProcessAsUser' est défini pour s'exécuter en tant qu'utilisateur actif. –

+0

'GetLastErrot' est appelé dans toutes les fonctions' ErrorLog'. Le 'sommeil (2000)' est là parce que le processus créé par le service prend trop longtemps pour ouvrir sa fin. Il ne peut pas avoir besoin de 2 secondes entières. Ce nombre a été placé là arbitrairement. –

+0

Bon à savoir si vous consignez les erreurs. Je suis curieux de l'appel à DestroyEnvironmentBlock. C'est à l'intérieur de la boucle mais je ne vois pas init à l'intérieur de la boucle. Cela pourrait être un bug bien que je pense que cela échouerait sur la deuxième passe pas la première (à moins que vous n'initiez pas du tout 'pEnv' du tout?). Vous ne pouvez pas obtenir une pile d'appel appropriée en exécutant ceci dans le débogueur jusqu'à ce que vous atteigniez l'exception? Vous devriez être capable de faire mieux que "après le journal de nettoyage" en le réduisant. En outre, vérifiez ** tous ** Appels d'API Win32 pour l'erreur. Si l'un échoue et que vous manquez ce fait, le comportement ultérieur est susceptible d'être inattendu. –

Questions connexes