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.. ?
how to know all sub-processes?
Re: how to know all sub-processes?
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.
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.
Re: how to know all sub-processes?
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
Re: how to know all sub-processes?
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
thanks for the example; I had the same basic idea going; but was missing something your code clued me in on.
Cheers
-josh

