16

We have a C++ task that will fork a new process. That process in turn may have several child processes. If the task runs past an allotted time, we will want to kill that forked process.

However, we don't want to orphan the processes it has spawned. We want them all to die. I have used Process Explorer and it has a "Kill Process Tree" option, similar to Windows Task Manager's "End Process Tree", so I'm guessing/assuming there is a public API to do this. Has anyone done this, or know of a reference to a public API that does?

Gama11
  • 31,714
  • 9
  • 78
  • 100
Brett McCann
  • 2,469
  • 2
  • 27
  • 44
  • I believe that the Task Manager does a variety of things that are not available via public APIs. – jdigital Mar 02 '09 at 23:41
  • while I would have no problem believing that ;) the fact that Process Explorer does it makes me wonder. I believe it was written before that company was acquired my MS. – Brett McCann Mar 02 '09 at 23:46
  • Yeah, but the guy who wrote process explorer - Mark Russinovich - used to work for Microsoft on Windows NT (before having his company bought by Microsoft) and he literarily wrote the book on Windows internals. http://www.microsoft.com/learning/en/us/books/12069.aspx – James Caccese Mar 02 '09 at 23:51
  • 1
    I can guarantee you that Process Explorer does things that are not documented. That was the whole point! – jdigital Mar 02 '09 at 23:58

5 Answers5

20

You might want to consider the "Jobs API". CreateJobObject and friends. You can enforce children processes to stay within the Job, by setting appropriate attribute. Then you can call TerminateJobObject whenever you want.

Clarification: this is NOT what Task Manager does.

Gama11
  • 31,714
  • 9
  • 78
  • 100
EFraim
  • 12,811
  • 4
  • 46
  • 62
  • 1
    follow up, if that forked process dies and orphans its jobs, will TerminateJobObject still be able to kill the orphans left behind? – Brett McCann Mar 02 '09 at 23:48
  • 2
    Yes, see relevant API doc. Unless a process was created with CREATE_BREAKAWAY_FROM_JOB flag. – EFraim Mar 02 '09 at 23:51
  • 2
    Though running away is not possible if JOB_OBJECT_LIMIT_BREAKAWAY_OK limit in the job object is not set. – EFraim Mar 02 '09 at 23:52
  • 1
    Beware of trouble with Vista's Explorer.exe. I've seen it put processes started through a shortcut in a job, preventing creating your own job. – Hans Passant Mar 03 '09 at 02:35
  • 1
    But if a child process spawns another processes there is a possibility that it also uses a job object to control them. So the assigning such project to a job object can lead to troubles of its execution, because [nested jobs are allowed starting only with Windows 8 and Windows Server 2012](http://msdn.microsoft.com/en-us/library/windows/desktop/hh448388(v=vs.85).aspx). – SerG Jun 24 '14 at 08:17
6

I suggest going the job object route, as indicated above, it will be the most reliable.

If you can't go the job object route, you can use the toolhelp API to get parent process ID's and build the tree that way. Be cautious though, since Windows doesn't have a strong parent/child relationship and it is possible for PID's to get recycled. You can use GetProcessTimes to query the creation time of the process, and check that it is older than the child. If an intermediate process in the tree is terminated, you will not be able to walk the tree further.

// Error handling removed for brevity
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 process;
ZeroMemory(&process, sizeof(process));
process.dwSize = sizeof(process);
Process32First(snapshot, &process);
do
{
    // process.th32ProcessId is the PID.
    // process.th32ParentProcessID is the parent PID.

} while (Process32Next(snapshot, &process));
Gama11
  • 31,714
  • 9
  • 78
  • 100
Michael
  • 54,279
  • 5
  • 125
  • 144
5

There is a Win32 function called TerminateProcess(). It should do the job for you.

Alternatively, I've found the taskkill command to be useful for things like this.

from the command line:

taskkill /F /T /IM program.exe

from code:

system("taskkill /F /T /IM program.exe");

other switches (straight from taskkill /? ):

 TASKKILL [/S system [/U username [/P
 [password]]]]
          { [/FI filter] [/PID processid | /IM imagename] } [/F] [/T]

 Description:
     This command line tool can be used to end one or more processes.
     Processes can be killed by the process id or image name.

 Parameter List:
     /S    system           Specifies the remote system to connect to.

     /U    [domain\]user    Specifies the user context under which
                            the command should execute.

     /P    [password]       Specifies the password for the given
                            user context. Prompts for input if omitted.

     /F                     Specifies to forcefully terminate
                            process(es).

     /FI   filter           Displays a set of tasks that match a
                            given criteria specified by the filter.

     /PID  process id       Specifies the PID of the process that
                            has to be terminated.

     /IM   image name       Specifies the image name of the process
                            that has to be terminated. Wildcard '*'
                            can be used to specify all image names.

     /T                     Tree kill: terminates the specified process
                            and any child processes which were started by it.

     /?                     Displays this help/usage.

-John

John T
  • 23,735
  • 11
  • 56
  • 82
1

You want to find the process id for the process you want to kill, then "walk the tree" of its children (and their children, and so on...), note their pids, and then kill all the processes nice and quickly.

James Caccese
  • 1,415
  • 1
  • 10
  • 18
0

You can also use WMI, route planning you can create a class to perform the tasks.
Se this "Where can I find the WMI documentation?"
and The WMI COM library
and WMI C++ Application Examples

Community
  • 1
  • 1
lsalamon
  • 7,998
  • 6
  • 50
  • 63