Code archives/BlitzPlus Gui/Process Tree

This code has been declared by its author to be Public Domain code.

Download source code

Process Tree by BlitzSupport2003
This program reads the list of running processes and displays them in a tree view, showing how child processes were spawned.
; -----------------------------------------------------------------------------
; Process list... see which processes spawned which programs!
; -----------------------------------------------------------------------------

; Works for me under Windows 2000, anyway...

; -----------------------------------------------------------------------------
; ADD TO kernel32.decls IN USERLIBS FOLDER!
; -----------------------------------------------------------------------------

; .lib "kernel32.dll"

; CreateToolhelp32Snapshot% (flags, th32processid)
; Process32First% (snapshot, entry*)
; Process32Next% (snapshot, entry*)
; Module32First% (snapshot, entry*)
; Module32Next% (snapshot, entry*)
; Thread32First% (snapshot, entry*)
; Thread32Next% (snapshot, entry*)
; Heap32First% (snapshot, entry*, th32heapid)
; Heap32Next% (entry*)
; Heap32ListFirst% (snapshot, entry*)
; Heap32ListNext% (snapshot, entry*)
; Toolhelp32ReadProcessMemory% (th32processid, baseaddress, buffer*, ReadBytes, bytesread)
; CloseHandle% (Object)

; -----------------------------------------------------------------------------
; PROCESSENTRY32 structure hack...
; -----------------------------------------------------------------------------
; Hopefully won't have to do this in BlitzMax... hint hint, Mark... :)
; -----------------------------------------------------------------------------

Const SizeOf_PE32 = 296

Type PE32

	Field bank
	
;    dwSize.l
;    cntUsage.l
;    th32ProcessID.l
;    th32DefaultHeapID.l
;    th32ModuleID.l
;    cntThreads.l
;    th32ParentProcessID.l
;    pcPriClassBase.l
;    dwFlags.l
;    szExeFile.b [#MAX_PATH]

End Type

; -----------------------------------------------------------------------------

; -----------------------------------------------------------------------------
; Create a new 'process' list entry...
; -----------------------------------------------------------------------------

Function CreatePE32.PE32 ()
	p.PE32 = New PE32
	p\bank = CreateBank (SizeOf_PE32)
	If p\bank
		PokeInt p\bank, 0, SizeOf_PE32
	Else
		Delete p
		Return Null
	EndIf
	Return p
End Function

; -----------------------------------------------------------------------------
; Free process list entry...
; -----------------------------------------------------------------------------

Function FreePE32 (p.PE32)
	If p\bank
		FreeBank p\bank
	EndIf
	Delete p
End Function

; -----------------------------------------------------------------------------
; Redundant info...
; -----------------------------------------------------------------------------

Function PrintProc (bank)
	Print ""
	Print "Name    : " + ProcessName$ (bank)
	Print "Usage   : " + PeekInt (bank, 4)
	Print "Proc ID : " + PeekInt (bank, 8)
	Print "Heap ID : " + PeekInt (bank, 12)
	Print "Mod  ID : " + PeekInt (bank, 16)
	Print "Threads : " + PeekInt (bank, 20)
	Print "Parent  : " + PeekInt (bank, 24)
	Print "ClasBas : " + PeekInt (bank, 28)
	Print "Flags   : " + PeekInt (bank, 32)
End Function

; -----------------------------------------------------------------------------
; Eeuurrggghhhh... leech process name from bank...
; -----------------------------------------------------------------------------

Function ProcessName$ (bank)
	For s = 36 To BankSize (bank) - 1
		byte = PeekByte (bank, s)
		If byte
			result$ = result$ + Chr (byte)
		Else
			Exit
		EndIf
	Next
	Return result$
End Function

Global PROC_COUNT

; -----------------------------------------------------------------------------
; Constants required by process functions, etc...
; -----------------------------------------------------------------------------

Const TH32CS_SNAPHEAPLIST = $1
Const TH32CS_SNAPPROCESS = $2
Const TH32CS_SNAPTHREAD = $4
Const TH32CS_SNAPMODULE = $8
Const TH32CS_SNAPALL = (TH32CS_SNAPHEAPLIST Or TH32CS_SNAPPROCESS Or TH32CS_SNAPTHREAD Or TH32CS_SNAPMODULE)
Const TH32CS_INHERIT = $80000000
Const INVALID_HANDLE_VALUE = -1
Const MAX_PATH = 260

; -----------------------------------------------------------------------------
; Take snapshot of running processes...
; -----------------------------------------------------------------------------

Function CreateProcessList ()
	PROC_COUNT = 0
	Return CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0)
End Function

; -----------------------------------------------------------------------------
; Free list of processes (created via CreateProcessList and GetProcesses)...
; -----------------------------------------------------------------------------

Function FreeProcessList (snap)
	For p.PE32 = Each PE32
		FreePE32 (p)
	Next
	CloseHandle (snap)
	PROC_COUNT = 0
End Function

Function GetProcesses (snap)

	PROC_COUNT = 0
	
	; Check snapshot is valid...
	
	If snap <> INVALID_HANDLE_VALUE
		
		; Hack up a PE32 (PROCESSENTRY32) structure...
		
		p.PE32 = CreatePE32 ()
		
		; Find the first process, stick info into PE32 bank...
		
		If Process32First (snap, p\bank)
	
			; Increase global process counter...
			
			PROC_COUNT = PROC_COUNT + 1
			
			Repeat
		
				; Create a new PE32 structure for every following process...
				
				p.PE32 = CreatePE32 ()
				
				; Find the next process, stick into PE32 bank...
				
				nextproc = Process32Next (snap, p\bank)
		
				; Got one? Increase process count. If not, free the last PE32 structure...
				
				If nextproc			
					PROC_COUNT = PROC_COUNT + 1
				Else
					FreePE32 (p)
				EndIf
				
			; OK, no more processes...
			
			Until nextproc = 0
			
		Else
		
			; No first process found, so delete the PE32 structure it used...
			
			FreePE32 (p)
			Return False
			
		EndIf
				
		Return True
	
	Else
	
		Return False
		
	EndIf
	
End Function

; -----------------------------------------------------------------------------
; Used to create a list of treeview nodes...
; -----------------------------------------------------------------------------

Type Node
	Field node
End Type

; -----------------------------------------------------------------------------
; Fill treeview gadget...
; -----------------------------------------------------------------------------

Function FillProcessTree (root)

	snap = CreateProcessList ()

	If GetProcesses (snap)
	
		For p.PE32 = Each PE32
			pid = PeekInt (p\bank, 8)
			parent = PeekInt (p\bank, 24)
			proc$ = ProcessName$ (p\bank)
			n.Node = New Node
			n\node = AddTreeViewNode (proc$, root)
			CompareProcs (p, n\node)
		Next
	
		FreeProcessList (snap)

	Else
		Notify "Failed to create process list!", True
	EndIf			

End Function

; -----------------------------------------------------------------------------
; Find child processes (ah, the joys of trial and error)...
; -----------------------------------------------------------------------------

Function CompareProcs (p.PE32, node)

	For q.PE32 = Each PE32
		
		If p <> q
		
			pid		= PeekInt (p\bank, 8)
			qid		= PeekInt (q\bank, 8)
			qparent = PeekInt (q\bank, 24)
		
			If pid = qparent
			
				proc$ = ProcessName (q\bank)
				n.Node = New Node
				n\node = AddTreeViewNode (proc$, node)
				CompareProcs (q, n\node)
				Delete q
				
			EndIf
		
		EndIf
		
	Next
	
End Function

; -----------------------------------------------------------------------------
; D E M O . . .
; -----------------------------------------------------------------------------

; Slight oddity: if it crashes, try sticking a second's Delay () in here. Seems
; to sometimes do this when run from the IDE (maybe snapshotting while a process
; is being spawned is buggy in Windoze? That's my story and I'm sticking to it)...

AppTitle "Process Tree..."

window = CreateWindow ("Process Tree...", 300, 200, 500, 350)

tree = CreateTreeView (0, 0, ClientWidth (window), ClientHeight (window) - 30, window)
root = TreeViewRoot (tree)
SetGadgetLayout tree, 1, 1, 1, 1

button = CreateButton ("Refresh list", 0, ClientHeight (window) - 25, 150, 21, window)
SetGadgetLayout button, 1, 0, 0, 1

menu = CreateMenu ("&File", 0, WindowMenu (window))
CreateMenu "&Refresh", 1, menu
CreateMenu "", 2, menu
CreateMenu "&About", 3, menu
CreateMenu "E&xit", 4, menu
UpdateWindowMenu window

FillProcessTree (root)

Repeat

	Select WaitEvent ()
	
		Case $803
			End
		
		Case $1001
			Select EventData ()
				Case 1
					FreeGadget tree
					tree = CreateTreeView (0, 0, ClientWidth (window), ClientHeight (window) - 30, window)
					root = TreeViewRoot (tree)
					SetGadgetLayout tree, 1, 1, 1, 1
					FillProcessTree (root)

				Case 3
					Notify "Process Tree..." + Chr (10) + Chr (10) + "An amazing Hi-Toro production, public domain 2003."
					
				Case 4
					End

			End Select
		Case $401
		
			Select EventSource ()

				Case button
				
					FreeGadget tree
					tree = CreateTreeView (0, 0, ClientWidth (window), ClientHeight (window) - 30, window)
					root = TreeViewRoot (tree)
					SetGadgetLayout tree, 1, 1, 1, 1
					FillProcessTree (root)

			End Select
			
	End Select

Forever

Comments

None.

Code Archives Forum