how to know all sub-processes?

Windows specific forum
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

how to know all sub-processes?

Post by jassing »

There must be a windows api or set of api's -- procexp can show you a "top down" tree of processes.
What I want to do is monitor a set of applications, and at a specific time, signal them all to terminate, and kill them forcably if they don't exit on their own. I can track the upper-level applications w/o much issue -- it's any sub-processes that they launch.

For example; explorer opens cmd which opens notepad
-Explorer.exe
+-cmd.exe
+-notepad.exe

So in my case:
MyMonitor.exe
-App1.exe
-App2.exe
-etc...

What I want to "know" (discover) is any processes/exe that app1 and app2 have launched, so I can know the tree of all apps starting with "myMonitor.exe" on down.

Is there an easy way to do this, or is it just a matter of enumerating all processes, querying their parent process and assembling the tree.. ?
Thorium
Addict
Addict
Posts: 1308
Joined: Sat Aug 15, 2009 6:59 pm

Re: how to know all sub-processes?

Post by Thorium »

A process has a parent process id. You can use that to build a hierarchical structure.

You can use CreateToolhelp32Snapshot API to enumerate the processes with informations including parent PID.
A search for CreateToolhelp32Snapshot on the forums should show some code.
Hi-Toro
Enthusiast
Enthusiast
Posts: 270
Joined: Sat Apr 26, 2003 3:23 pm

Re: how to know all sub-processes?

Post by Hi-Toro »

Here's a graphical example that shows all processes and their children, but if you want to strip it down, retrieval of the process list is done just after window creation, then the CompareProcs function looks through the list to see which processes were launched by other processes in the list.

Code: Select all


; -----------------------------------------------------------------------------
; GLOBAL PROCESS LIST! Used to retrieve information after getting process list...
; -----------------------------------------------------------------------------

Global NewList Process32.PROCESSENTRY32 () 

Global ps
Global Deficon

#LIST_MODULES_ALL = $3

Procedure.s GetPath (pid)

    ; XP and above only! Processes on NT only return exe name by default...

    If ps ; Global storing psapi.dll handle If available...

		handle = OpenProcess_ (#PROCESS_QUERY_INFORMATION | #PROCESS_VM_READ, 0, pid)
        
        If handle
	        If CallFunction (ps, "EnumProcessModulesEx", handle, @module, 4, @needed, #LIST_MODULES_ALL)
                f$ = Space (#MAX_PATH)
                If CallFunction (ps, "GetModuleFileNameExA", handle, module, @f$, #MAX_PATH)
                    ;Debug f$
                EndIf
            EndIf
            CloseHandle_ (handle)
        EndIf
        
	EndIf
	
	ProcedureReturn f$

EndProcedure

; This function sorts processes into TreeGadget list, so that child processes branch off from parents...

Procedure CompareProcs (gadget, currentid, currentname$, indent)

    ;Debug "Comparing " + currentname$ + " [" + Str (currentid) + "]"
    
    ResetList (Process32 ())
    
    While NextElement (Process32 ())

        ; Skip if checking against 'currentid', ie. same process...
                
        If Process32 ()\th32ProcessID <> currentid
            
            ; Check currentid against this one...
            
            againstid = Process32 ()\th32ProcessID
            againstparent = Process32 ()\th32ParentProcessID
        
            ; If 'currentid' is parent of this process...
            
            If currentid = againstparent
            
                proc$ = PeekS (@Process32 ()\szExeFile)
                
                indent = indent + 1

				p$ = GetPath (Process32 ()\th32ProcessID)
				If p$ = ""
			 		p$ = PeekS (@Process32 ()\szExeFile)
				EndIf
				
				image = ExtractIcon_ (GetModuleHandle_ (#Null), p$, 0)
				If Not image
					image = Deficon
				EndIf
				
				AddGadgetItem (0, -1, p$, image, indent)

                current = ListIndex (Process32 ())
                CompareProcs (gadget, againstid, proc$, indent)
                
                SelectElement (Process32 (), current)
                DeleteElement (Process32 ())

				indent = indent - 1
			
            EndIf
            
        EndIf
        
    Wend
    
EndProcedure

; Window hook, used to resize/redraw TreeGadget when window is resized...

Procedure WinHook (WindowID, Message, wParam, lParam)
    If Message = #WM_PAINT
        ResizeGadget (0, 0, 0, WindowWidth (0), WindowHeight (0))
        RedrawWindow_ (GadgetID (0), #Null, #Null, #RDW_INVALIDATE)
    EndIf
    ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

ps = OpenLibrary (#PB_Any, "psapi.dll")

; Add processes to Process32 () list...

k32 = OpenLibrary (#PB_Any, "kernel32.dll")

If k32

    snap = CallFunction (k32, "CreateToolhelp32Snapshot", #TH32CS_SNAPPROCESS, 0)

    If snap <> #INVALID_HANDLE_VALUE ; BUG FIX AS PER http://msdn.microsoft.com/msdnmag/issues/02/06/Debug/Default.aspx

        Proc32.PROCESSENTRY32
        Proc32\dwSize = SizeOf (PROCESSENTRY32)
        
        If CallFunction (k32, "Process32First", snap, @Proc32)

            AddElement (Process32 ())
            CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32))
            
            While CallFunction (k32, "Process32Next", snap, @Proc32)
                AddElement (Process32 ())
                CopyMemory (@Proc32, @Process32 (), SizeOf (PROCESSENTRY32))
            Wend
            
        EndIf
        
        CloseHandle_ (snap)

    EndIf

    CloseLibrary (k32)
    
EndIf

Deficon = LoadIcon_ (#Null, #IDI_APPLICATION)

; GUI...

OpenWindow (0, 0, 0, 800, 600, "Process list...", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
TreeGadget (0, 0, 0, WindowWidth (0), WindowHeight (0))

SetWindowCallback (@WinHook ())

; Add processes to TreeGadget...

ResetList (Process32 ())

While NextElement (Process32 ())

	p$ = GetPath (Process32 ()\th32ProcessID)
	If p$ = ""
 		p$ = PeekS (@Process32 ()\szExeFile)
	EndIf
	
	image = ExtractIcon_ (GetModuleHandle_ (#Null), p$, 0)
	If Not image
		image = Deficon
	EndIf

	AddGadgetItem (0, -1, p$, image, indent)
    current = ListIndex (Process32 ())
    CompareProcs (0, Process32 ()\th32ProcessID, PeekS (@Process32 ()\szExeFile), 0)
    SelectElement (Process32 (), current)
    
Wend

For item = 0 To CountGadgetItems (0) - 1
    SetGadgetItemState (0, item, #PB_Tree_Expanded)
Next

Repeat

	Select WaitWindowEvent ()
		Case #PB_Event_CloseWindow
			Break
	EndSelect
	
ForEver

If ps
	CloseLibrary (ps)
EndIf

End
James Boyd
http://www.hi-toro.com/
Death to the Pixies!
jassing
Addict
Addict
Posts: 1885
Joined: Wed Feb 17, 2010 12:00 am

Re: how to know all sub-processes?

Post by jassing »

Thanks; I wanted to be sure I wasn't missing an easy(ier) way..
thanks for the example; I had the same basic idea going; but was missing something your code clued me in on.
Cheers
-josh
Post Reply