Sign in to follow this  
Followers 0
JerryD

UDF: _ChildProcess - Children processes of a PID

1 post in this topic

I've encountered installations that run using something like SETUP.EXE that spawn processes (usually msiexec) that may continue running after setup has exited. If I'm running multiple installations, a subsequent installation may fail if there are still processes running from the previous installation.

I've developed the UDF _ChildProcess that returns an array containing the number of children processes running in the [0][0] element, and information about the child processes running.

#include-once

#region Sample Code
;#cs
#include <array.au3>
$ProcList = ProcessList ( )
For $i = 1 To $ProcList[0][0]
    $Child = _ChildProcess ( $ProcList[$i][1] )
    $Err = @error
    If $Child[0][0] > 0 Then
        _ArrayDisplay ( $Child, 'Children of ' & $ProcList[$i][0] & ' [' & $ProcList[$i][1] & ']' & ' - Error: ' & $Err )
    EndIf
Next
;#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

I suppose you could even get the exit codes of all the child processes, but it would be hard to determine when to aquire the children PID's.

Thanks again to SvenP's for his wonderful WMI ScriptOMatic tool for AutoIt that makes this kind of thing child's play!

(PUN INTENDED!)

ps - At the last minute I was thinking of creating another UDF that just returned the number of child processes in the hopes of not having to do the FOR loop on each object. I tried a lot of different combinations of $colItems like $colItems.Count and $colItems.ALL, but none worked. Is there a way to get the number of items returned by the $objWMIService.ExecQuery call?

Thanks.

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
Sign in to follow this  
Followers 0