2008-09-26 7 views
0

J'ai une DLL qui est chargée dans un processus parent tiers en tant qu'extension. À partir de cette DLL, j'instancie des processus externes (les miens) en utilisant l'API CreateProcess. Cela fonctionne très bien dans 99,999% des cas, mais parfois cela échoue soudainement et arrête de fonctionner de manière permanente (peut-être un redémarrage du processus parent résoudrait cela mais ce n'est pas souhaitable et je ne veux pas le recommander avant de résoudre le problème). l'échec est symptomized par un processus externe non invoqué plus, même si CreteProcess() ne signale pas une erreur et par GetExitCodeProcess() retour 128. Voici la version simplifiée de ce que je fais:GetExitCodeProcess() renvoie 128

STARTUPINFO si; 
ZeroMemory(&si, sizeof(si)); 
si.cb = sizeof(si); 
si.dwFlags = STARTF_USESHOWWINDOW; 
si.wShowWindow = SW_HIDE; 

PROCESS_INFORMATION pi; 
ZeroMemory(&pi, sizeof(pi)); 

if(!CreateProcess(
    NULL, // No module name (use command line). 
    "<my command line>", 
    NULL, // Process handle not inheritable. 
    NULL, // Thread handle not inheritable. 
    FALSE, // Set handle inheritance to FALSE. 
    CREATE_SUSPENDED, // Create suspended. 
    NULL, // Use parent's environment block. 
    NULL, // Use parent's starting directory. 
    &si, // Pointer to STARTUPINFO structure. 
    &pi)) // Pointer to PROCESS_INFORMATION structure. 
{ 
    // Handle error. 
} 
else 
{ 
    // Do something. 

    // Resume the external process thread. 
    DWORD resumeThreadResult = ResumeThread(pi.hThread); 
    // ResumeThread() returns 1 which is OK 
    // (it means that the thread was suspended but then restarted) 

    // Wait for the external process to finish. 
    DWORD waitForSingelObjectResult = WaitForSingleObject(pi.hProcess, INFINITE); 
    // WaitForSingleObject() returns 0 which is OK. 

    // Get the exit code of the external process. 
    DWORD exitCode; 
    if(!GetExitCodeProcess(pi.hProcess, &exitCode)) 
    { 
     // Handle error. 
    } 
    else 
    { 
     // There is no error but exitCode is 128, a value that 
     // doesn't exist in the external process (and even if it 
     // existed it doesn't matter as it isn't being invoked any more) 
     // Error code 128 is ERROR_WAIT_NO_CHILDREN which would make some 
     // sense *if* GetExitCodeProcess() returned FALSE and then I were to 
     // get ERROR_WAIT_NO_CHILDREN with GetLastError() 
    } 

    // PROCESS_INFORMATION handles for process and thread are closed. 
} 

processus externe peut être appelé manuellement à partir de l'Explorateur Windows ou de la ligne de commande et il démarre très bien tout seul. Appelé comme ça, avant de faire un vrai travail, crée un fichier journal et consigne des informations à son sujet. Mais invoqué comme décrit ci-dessus cette information de journalisation n'apparaît pas du tout donc je suppose que le thread principal du processus externe n'entre jamais dans main() (Je teste cette supposition maintenant.)

Il y a au moins une chose que je pourrais faire pour essayer de contourner le problème (pas démarrer le fil suspendu) mais je voudrais d'abord comprendre la racine de l'échec en premier. Est-ce que quelqu'un a une idée de ce qui pourrait causer cela et comment le réparer?

+0

Oublié de recommander l'édition: J'ai clarifié pourquoi je suppose que le processus externe ne s'exécute jamais et j'ai clarifié pourquoi je ne pense pas que l'explication ERROR_WAIT_NO_CHILDREN est appropriée. –

Répondre

1

Citation de l'article de MSDN sur GetExitCodeProcess:

Les états de terminaison suivants peut être retourné si le processus est terminé:

  • La valeur de sortie spécifié dans le ExitProcess ou TerminateProcess fonction
  • La valeur de retour de la fonction principale ou WinMain du processus
  • La valeur d'exception pour une exception non gérée qui a provoqué le processus de mettre fin à

Compte tenu du scénario que vous avez décrit, je pense que la cause la plus probable ist troisième: Une exception non gérée. Jetez un oeil à la source des processus que vous créez.

+1

code d'erreur 128 de RROR_WAIT_NO_CHILDREN 0x80 Il n'y a pas de processus enfant à attendre. –

+0

Oui, j'ai examiné. Immédiatement avant toute chose, le processus configure la consignation et enregistre le démarrage. Cela n'apparaît jamais. Je sais que la journalisation devrait réussir puisque DLL (en cours d'exécution dans le processus parent) peut créer des fichiers journaux, par conséquent le processus enfant devrait être capable de les créer aussi. –

+0

Roman, j'ai pensé à cela aussi mais au pire cela ne devrait pas être retourné comme code de sortie de GetExitCodeProcess() Peut-être qu'il pourrait être retourné comme GetLastError() mais GetExitCodeProcess() n'indique pas une erreur en premier lieu TRUE) –

0

Il y a 2 questions que je pouvais penser de votre exemple de code

1.Get de yourusage des 2 premiers paramaters à la commande creatprocess de travail d'abord. Codez les chemins et appelez notepad.exe et voyez si cela arrive. Continuez à peaufiner ceci jusqu'à ce que vous ayez exécuté le bloc-notes.

2.Contrairement à votre commentaire, Si vous avez passé le paramètre currentdirectory pour le nouveau processus comme NULL, il utilisera le répertoire de travail en cours du processus pour démarrer le nouveau processus et non le répertoire de départ parent.

Je suppose que votre processus externe exe ne peut pas démarrer correctement en raison de dépendances dll qui ne peuvent pas être résolues dans le nouveau chemin.

ps: la veille du débogueur pour @ err, hr qui vous dira l'explication du dernier code d'erreur,

+0

Merci pour la réponse - bonne capture sur le commentaire. Votre explication a du sens, mais ce n'est pas ça. Le problème est dans l'emballage de protection utilisé par l'entreprise. Quand j'ai envoyé le même exe sans ça, ça a marché sans problèmes. Je posterai l'explication. –

+0

Salut, Je suis confronté à un problème similaire, pourriez-vous s'il vous plaît poster l'explication. – Naga

1

Jetez un oeil à la mémoire de bureau Heap. Essentiellement, le problème du tas de bureau se résume à épuiser les ressources (par exemple en démarrant trop de processus).Lorsque votre application est à court de ces ressources, l'un des symptômes est que vous ne pourrez pas démarrer un nouveau processus et l'appel à CreateProcess échouera avec le code 128.

Notez que le contexte dans lequel vous exécutez également a un effet. Par exemple, en cours d'exécution en tant que service, vous serez à court de tas de bureau beaucoup plus rapidement que si vous testez votre code dans une application de console.

Ce post a beaucoup de bonnes informations sur tas de bureau

Microsoft Support a également des informations utiles.

Questions connexes