rudi Posted November 19, 2020 Share Posted November 19, 2020 (edited) Hello, based on @JerryD 's function I added some lines to watch for child processes recursively. That's helful for installing Autodesk patches silently all-in-a-row: Some of these patches respawn the setup program, then terminate the original PID, and the respawned PID as well spawns other child processes. Before launching the next patch, it's required to wait for *ALL* child PID to vanish. The sample script below will show what I mean. the script launches a CMD.EXE and then checks for child / grand-child /... processes over and over again. After every step close the _debugarraydisplay() to refresh it! Lauch a new CMD box by typing start cmd do that two more times in each new opened CMD box Now launch from box #1 another program, e.g. start notepad.exe Do the same for the box #2 with a different program start winword.exe and for box #3 as well start calc.exe Now you can close the original box#1 and box#2, if you launch new processes from box#3 they will be captured and monitored as well. expandcollapse popup#include <Debug.au3> #include <array.au3> $TLDPID=Run("CMD.EXE") Dim $aCHLDPIDs[0][2] Enum $iPID,$iName $SubLevel=0 do AddChldPidsRec($TLDPID) ; recursively search for Children, Grandchildren, Grand-grand-children... _DebugArrayDisplay($aCHLDPIDs,"Alle Child PIDs") for $y = 0 to UBound($aCHLDPIDs) - 1 AddChldPidsRec($aCHLDPIDs[$y][$iPID]) ; Check all PIDs in the list again: There might be a new "Grand-Child" we need to wait for, while the "child" has died *ALREADY* (chain broken) Next until AllGone() Func AddChldPidsRec($_PID) $SubLevel+=1 ConsoleWrite($SubLevel & @TAB & $_PID & @CRLF) Local $p,$NextPID,$KnownPID $a2Children=_ChildProcess($_PID) if IsArray($a2Children) Then ; _DebugArrayDisplay($a2Children,$SubLevel & " [" & $_PID & "]") for $p = 1 to $a2Children[0][0] $NextPID=$a2Children[$p][$iPID] $NextProg=$a2Children[$p][$iName] ;~ MsgBox(0,"NextPID",$NextPID & @CRLF & $NextProg) if (_ArraySearch($aCHLDPIDs,$NextPID)= -1) then _ArrayAdd($aCHLDPIDs,$NextPID & "|" & $NextProg) ; diese PID ist noch nicht erfasst. AddChldPidsRec($NextPID) ; Check this PID for decendent child PIDs, too. (recursive check) Next Else MsgBox(0,$_PID,"no child PIDs") EndIf $SubLevel-=1 EndFunc Func AllGone() local $x for $x = UBound($aCHLDPIDs) - 1 to 0 Step -1 if ProcessExists($aCHLDPIDs[$x][$iPID]) Then ; Prozess läuft noch Else _ArrayDelete($aCHLDPIDs,$x) EndIf Next ; _DebugArrayDisplay($aCHLDPIDs,"AllGoneCheck: Noch was da!") if UBound($aCHLDPIDs) > 0 or ProcessExists($TLDPID) Then Return False Else MsgBox(0,"All gone","Ready for exit") Return True EndIf EndFunc ;#ce #endregion Sample Code ;=============================================================================== ; Function Name: _ChildProcess ; Description: Returns an array containing child process info ; Parameter(s): $iParentPID - Parent Process PID ; ; Requirement(s): AutoIt 3.8+ ; Return Value(s): two dimensional array $aChildren[][] as follows ; $aChildren[0][0] = Number of children found ; ; $aChildren[x][0] = Child Process's PID (called Handle, but not a handle object) ; $aChildren[x][1] = Child Process's Name ; $aChildren[x][2] = Child Process's Command Line ; $aChildren[x][3] = Child Process's Executable Path ; $aChildren[x][4] = Child Process's Creation Date and Time ; $aChildren[x][5] = Child Process's Session Id ; $aChildren[x][6] = Child Process's Status ; $aChildren[x][7] = Child Process's Termination Date ; ; AutoIt Version: 3.2.8.1 ; Author: JerryD ;=============================================================================== Func _ChildProcess ( $iParentPID ) Local Const $wbemFlagReturnImmediately = 0x10, $wbemFlagForwardOnly = 0x20 Local Const $sQuery = 'SELECT * FROM Win32_Process Where ParentProcessId = ' & $iParentPID & ' AND Handle <> ' & $iParentPID Local $aChildren[1][8] $aChildren[0][0] = 0 $aChildren[0][1] = 'Name' $aChildren[0][2] = 'Command Line' $aChildren[0][3] = 'Executable Path' $aChildren[0][4] = 'Creation Date and Time' $aChildren[0][5] = 'Session Id' $aChildren[0][6] = 'Status' $aChildren[0][7] = 'Termination Date' Local $objWMIService = ObjGet ( 'winmgmts:\\localhost\root\CIMV2' ) If NOT IsObj ( $objWMIService ) Then SetError ( 1 ) Return $aChildren EndIf Local $colItems = $objWMIService.ExecQuery ( $sQuery, 'WQL', $wbemFlagReturnImmediately + $wbemFlagForwardOnly ) If IsObj($colItems) then For $objItem In $colItems $aChildren[0][0] += 1 ReDim $aChildren[$aChildren[0][0]+1][8] $aChildren[$aChildren[0][0]][0] = $objItem.Handle $aChildren[$aChildren[0][0]][1] = $objItem.Name $aChildren[$aChildren[0][0]][2] = $objItem.CommandLine $aChildren[$aChildren[0][0]][3] = $objItem.ExecutablePath $aChildren[$aChildren[0][0]][4] = $objItem.CreationDate $aChildren[$aChildren[0][0]][5] = $objItem.SessionId $aChildren[$aChildren[0][0]][6] = $objItem.Status $aChildren[$aChildren[0][0]][7] = $objItem.TerminationDate Next Else SetError ( 2 ) Return $aChildren EndIf SetError ( 0 ) Return $aChildren EndFunc Edited November 19, 2020 by rudi Earth is flat, pigs can fly, and Nuclear Power is SAFE! Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now