tags:

views:

140

answers:

4

Is it possible to wait for all processes launched by a child process in Windows? I can't modify the child or grandchild processes.

Specifically, here's what I want to do. My process launches uninstallA.exe. The process uninistallA.exe launches uninstallB.exe and immediately exits, and uninstallB.exe runs for a while. I'd like to wait for uninstallB.exe to exit so that I can know when the uninstall is finished.

A: 

Use a named mutex.

Cheeso
I don't think I can do that. I can't modify the child processes.
thudbang
yeah, that won't work, then.
Cheeso
A: 

One possibility is to install Cygwin and then use the ps command to watch for the grandchild to exit

David Harris
+1  A: 

There is not a generic way to wait for all grandchildren but for your specific case you may be able to hack something together. You know you are looking for a specific process instance. I would first wait for uninstallA.exe to exit (using WaitForSingleObject) because at that point you know that uninstallB.exe has been started. Then use EnumProcesses and GetProcessImageFileName from PSAPI to find the running uninstallB.exe instance. If you don't find it you know it has already finished, otherwise you can wait for it.

An additional complication is that if you need to support versions of Windows older than XP you can't use GetProcessImageFileName, and for Windows NT you can't use PSAPI at all. For Windows 2000 you can use GetModuleFileNameEx but it has some caveats that mean it might fail sometimes (check docs). If you have to support NT then look up Toolhelp32.

Yes this is super ugly.

J. Loomis
You might consider using Toolhelp32 anyway, simply because it provides the parent (spawning) ID of each process, and CreateProcess() returns a Process ID as well. You should be able to launch uninstallA.exe, get its Process ID, and then use ToolHelp32 to look for all processes that were started by that same Process ID. Until you close the process handle returned by CreateProcess(), the OS cannot reuse uninstallA's Process ID.
Remy Lebeau - TeamB
+3  A: 

Create a Job Object with CreateJobObject. Use CreateProcess to start UninstallA.exe in a suspended state. Assign that new process to your job object with AssignProcessToJobObject. Start UninstallA.exe running by calling ResumeThread on the handle of the thread you got back from CreateProcess. Use WaitForSingleObject on the job object's handle, which will be signaled when there are no more processes executing in the job object -- i.e. UninstallB.exe has finished (and if it happened to start an UninstallC.exe, you'd automatically wait until that was finished too).

Jerry Coffin
Thanks. It looks like a simple WaitForSingleObject won't tell me when all processes have exited, but it looks like I can create an IO completion port and wait for JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO.
thudbang