7
votes

En attente des processus de petits-enfants dans Windows

est-il possible d'attendre tous les processus lancés par un processus enfant sous Windows? Je ne peux pas modifier les processus enfant ou petit-enfant.

Plus précisément, voici ce que je veux faire. Mon processus lance uninstalla.exe. Le processus UNINISTALLA.EXE lance uninstallb.exe et des sorties immédiatement, et uninstallb.exe s'exécute pendant un moment. J'aimerais attendre uninstallb.exe de sortir afin que je puisse savoir quand la désinstallation est terminée.


0 commentaires

5 Réponses :


0
votes

Utilisez un Nommé Mutex .


1 commentaires

Je ne pense pas que je puisse faire ça. Je ne peux pas modifier les processus de l'enfant.



0
votes

Une possibilité est d'installer Cygwin, puis d'utiliser la commande PS pour surveiller le petit-enfant pour quitter


0 commentaires

1
votes

Il n'y a pas une façon générique d'attendre tous les petits-enfants, mais pour votre cas spécifique, vous pourrez peut-être pirater quelque chose ensemble. Vous savez que vous recherchez une instance de processus spécifique. J'attendrais d'abord pour que Uninstalla.exe soit quittant (en utilisant WaitforsingleObject) car à ce stade, vous savez que UNINSTALLB.EXE a été démarré. Ensuite, utilisez énumprocesses et getProcessImageFileName de PSAPI pour trouver l'instance d'exécution de Uninstallb.exe. Si vous ne trouvez pas que vous savez que cela a déjà terminé, sinon vous pouvez l'attendre.

Une complication supplémentaire est que si vous devez prendre en charge les versions des fenêtres plus âgées que XP, vous ne pouvez pas utiliser getProcessImageFilename, et pour Windows NT, vous ne pouvez pas utiliser PSAPI du tout. Pour Windows 2000, vous pouvez utiliser GetModuleFilenameEx, mais il a des mises en garde qui signifient que cela pourrait échouer parfois (vérifier les documents). Si vous devez prendre en charge NT, recherchez ToolHelP32.

Oui c'est super moche.


1 commentaires

Vous pouvez envisager d'utiliser ToolHelP32 de toute façon, simplement car il fournit l'ID parent (frai) de chaque processus, et CreateProcess () renvoie également un identifiant de processus. Vous devriez pouvoir lancer uninstalla.exe, obtenir son identifiant de processus, puis utiliser ToolHelP32 pour rechercher tous les processus commencés par ce même identifiant de processus. Jusqu'à ce que vous fermiez la poignée de processus renvoyée par CreateProcess (), le système d'exploitation ne peut pas réutiliser l'ID de processus de la désinstallation.



9
votes

Créer un objet de travail avec CreateJobObject . Utilisez CreateProcess pour démarrer uninstalla.exe dans un état suspendu. Attribuez ce nouveau processus à votre objet de travail avec assignprocesstojobObject . Démarrer Uninstalla.exe S'exécuter en appelant Resumethread sur la poignée du fil que vous avez reculé de CreateProcess .

Puis la partie difficile: attendez que l'objet de travail achète son exécution. Malheureusement, cela est un peu plus complexe que quiconque espère raisonnablement. L'idée de base est que vous créez un port d'achèvement d'E / S, puis vous créez l'objet d'objet, associez-le avec le port d'achèvement d'E / S, puis attendez-le sur le port d'achèvement d'E / S (obtenir son statut avec GetQueDecPleTionnstatus ). Raymond Chen a une démonstration (et explique comment cela est venu) sur son Blog .


3 commentaires

Merci. Il ressemble à une simple attente pour serviraObject ne me le dira pas lorsque tous les processus sont sortis, mais on dirait que je peux créer un port d'achèvement de l'IO et attendre Job_Object_msg_Active_Process_Zero.


Raymond Chen couvre que dans son blog: Comment puis-je attendre jusqu'à ce que tous les processus dans un travail?


Mise à jour du lien vers Raymond Chen's Blog: Comment puis-je attendre que tous les processus d'emploi ont quitté?



2
votes

Voici une technique qui, sans infaillible, peut être utile si pour une raison quelconque, vous ne pouvez pas utiliser d'objet d'emploi. L'idée est de créer un tuyau anonyme et de laisser le processus enfant hériter de la poignée à l'extrémité d'écriture du tuyau.

Typiquement, les processus de petits-enfants hériteront également de l'extrémité d'écriture du tuyau. En particulier, les processus lancés par cmd.exe (par exemple, à partir d'un fichier de commandes) hériteront des poignées.

Une fois le processus d'enfant exité, le processus parent ferme sa poignée à la Écrivez l'extrémité du tuyau, puis tente de lire dans le tuyau. Puisque personne ne écrit sur le tuyau, l'opération de lecture bloquera indéfiniment. (Bien sûr, vous pouvez utiliser des threads ou des E / S asynchrones si vous souhaitez continuer à faire des choses en attendant les petits-enfants.)

quand (et seulement lorsque) la dernière poignée à l'extrémité d'écriture du tuyau est fermé, l'extrémité d'écriture du tuyau est automatiquement détruite. Cela casse la tuyau et l'opération de lecture complète et rapporte une défaillance erron_broken_pipe.

J'utilise ce code (et versions antérieures du même code) dans la production pendant plusieurs années. xxx


0 commentaires