Identify and Kill Child Process

fezbro

Member
Joined
Jul 24, 2006
Messages
7
Programming Experience
Beginner
I have a piece of code that starts a program and runs several parameters. Based on different occurences through the day it can start multiple instances of the same program. At certain points in the programs execution it starts another process. When I start the main program I attach it to a variable so I know what the process ID is so I can kill it.

I can't get hold of the correct process ID of the child process that was launched by the parent I'm trying to kill. I want to kill both the patent and ONLY it's associated child process.

Can anyone help?
 
You say that you are having problems determining the child threads of an instance of your app, but surely if you terminate the main thread then all of it's child threads will be terminated also, this is what happens by design.
 
Maybe not a child

When I kill the main process that I originally launch (called Runmac32.exe), that process then causes another process to start called Autoexe.exe. When I kill the Runmac32 process for the failed program, it still leave the Autoexe.exe process behind. I know the runmac32 program causes the autoexe process to be created.
There are several runmac32 processes running at any one time, and when everything works fine the processes (runmac32 AND its associated autoexe) start and finish fine. If the program that one of the runmac32 processes is controlling falls over, I need to be able to kill the runmac32 process AND the autoexe process that is associated with it.
:confused:
 
Threads and processes is not the same thing. If you kill a process its main thread and all its child threads are stopped. 'Child' processes are not affected, in the case above when parent process is killed the child is attached to the higher level parent.

Now on to what you ask, a process can start another process as you say, for instance with Process.Start method, the parent of that new process is then set to the one that started it, because all processes must have a parent. You can see the whole process tree (and much other info) with Sysinternals ProcessExplorer or similar tool http://www.sysinternals.com/Utilities/ProcessExplorer.html

For the operating system the child of a process doesn't matter, only that it is attached to a parent process, so you have to check all processes to see if its parent is your process. For some funny reason .Net framework Process class doesn't provide information about the parent process id, you have to use WMI or Win32 API.

Here is some sample code that gets all childs of current process with WMI, only one level is checked, the processes that are direct childs of the pid in question. Each child could of cource have childs of its own, so if you want to make a full process tree you have to do something clever.
VB.NET:
'   The results are added to a Listbox
 
'   To use WMI you must Add Reference to System.Management.dll in .Net tab of dialog, and also import the namespace.
 
'Imports System.Management
 
Sub pidWMI()
  Dim myId As Integer = Process.GetCurrentProcess.Id
  ListBox1.Items.Clear()
  Dim selectQuery As SelectQuery = New SelectQuery("Win32_Process")
  Dim searcher As New ManagementObjectSearcher(selectQuery)
  For Each proc As ManagementObject In searcher.Get
  If proc("ParentProcessId") = myId Then
    ListBox1.Items.Add(String.Format("{0} {1}", proc("Name"), proc("ProcessId").ToString))
  End If
  Next
End Sub
 
Last edited:
Just in case you or others want to try the Win32 APIs too, here is the same sample as above (some times WMI don't work..)
VB.NET:
'Imports System.Runtime.InteropServices
 
Sub pidWin32()
  ListBox1.Items.Clear()
  Dim hSnapshot As Integer = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
  If hSnapshot <> INVALID_HANDLE_VALUE Then
    Dim pcs As Process
    Dim myId As Integer = Process.GetCurrentProcess.Id
    Dim pe As New PROCESSENTRY32
    pe.dwSize = Marshal.SizeOf(pe)
    Dim ret As Boolean = Process32First(hSnapshot, pe)
    Dim lasterr As Integer = GetLastError
    While lasterr <> ERROR_NO_MORE_FILES
      If ret = True AndAlso pe.th32ParentProcessID = myId Then
        pcs = Process.GetProcessById(pe.th32ProcessID)
        ListBox1.Items.Add(String.Format("{0} {1}", pcs.[SIZE=2]ProcessName[/SIZE], pe.th32ProcessID))
      End If
      ret = Process32Next(hSnapshot, pe)
      lasterr = GetLastError
    End While
    CloseHandle(hSnapshot)
  End If
End Sub

'the declarations for Win32 needed:
VB.NET:
<StructLayout(LayoutKind.Sequential)> _
Structure PROCESSENTRY32
  Public dwSize As Int32
  Public cntUsage As Int32
  Public th32ProcessID As Int32
  Public th32DefaultHeapID As Int32
  Public th32ModuleID As Int32
  Public cntThreads As Int32
  Public th32ParentProcessID As Int32
  Public pcPriClassBase As Int32
  Public dwFlags As Int32
  <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _
  Public szExeFile As String
End Structure
 
Const MAX_PATH As Int32 = 260
Const TH32CS_SNAPPROCESS As Int32 = &H2
[SIZE=2][COLOR=#0000ff][COLOR=black]Const[/COLOR][/COLOR][/SIZE][COLOR=black][SIZE=2] INVALID_HANDLE_VALUE [/SIZE][SIZE=2]As[/SIZE][/COLOR][SIZE=2][COLOR=black] Int32 = -1[/COLOR]
[/SIZE][COLOR=black][SIZE=2]Const[/SIZE][SIZE=2] ERROR_NO_MORE_FILES [/SIZE][SIZE=2]As[/SIZE][SIZE=2] Int32 = 18I
[/SIZE][/COLOR]
Declare Function Process32First Lib "KERNEL32.dll" (ByVal hSnapshot As Int32, ByRef lppe As PROCESSENTRY32) As Int32
Declare Function Process32Next Lib "KERNEL32.dll" (ByVal hSnapshot As Int32, ByRef lppe As PROCESSENTRY32) As Int32
Declare Function CreateToolhelp32Snapshot Lib "KERNEL32.dll" (ByVal dwFlags As Int32, ByVal th32ProcessID As Int32) As Int32
Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Int32) As Int32
[SIZE=2][COLOR=#0000ff][COLOR=black]Declare [/COLOR][/COLOR][/SIZE][COLOR=black][SIZE=2]Function[/SIZE][SIZE=2] GetLastError [/SIZE][SIZE=2]Lib[/SIZE][SIZE=2]"kernel32.dll"[/SIZE][SIZE=2] () [/SIZE][SIZE=2]As[/SIZE][SIZE=2] Int32
[/SIZE][/COLOR]
 
Last edited:
WMI Error Message

I've tried doing the WMI call and get the following error mesage when I run it and it gets to the "If proc("ParentProcessId") = myId Then" line: -

Cast from type 'UInt32' to type 'Integer' is not valid

What am I doing wrong?


 
I don't know, I ain't getting no such error.
 
Back
Top