Jump to content
rudi

Watch Child Processes recursively

Recommended Posts

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!

  1. Lauch a new CMD box by typing 
    start cmd

     

  2. do that two more times in each new opened CMD box

  3. Now launch from box #1 another program, e.g.
    start notepad.exe
  4. Do the same for the box #2 with a different program
    start winword.exe

     

  5. and for box #3 as well
    start calc.exe

     

image.png.3bac390391ce9b8c8ebb4f28d5d36b91.png

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.

 

#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 by rudi

Earth is flat, pigs can fly, and Nuclear Power is SAFE!

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.

×
×
  • Create New...