Sign in to follow this  
Followers 0
UEZ

[Solved] Parent Process & Child Process

15 posts in this topic

#1 ·  Posted (edited)

Is it possible to get the parent process which has started my process?

E.g.

When I created a screensaver and rundll32.exe starts my ss in preview window then rundll32.exe is the parent process and my ss is a child process of it!

Further can I get the amount of child processes which has e.g. rundll32.exe has started?

<Parent process> PID 1000 (e.g. rundll32.exe)

├-----> <Child Process 1> PID 2000

├-----> <Child Process 2> PID 2001

├-----> <Child Process 2> PID 2002 (e.g. my program)

├-----> <Child Process n> PID m

Thanks,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

There's the WMI way: http://www.autoitscript.com/forum/index.ph...st&p=555530

But I'm not a fan of WMI because not every PC has it running or permissions to run it.

I wrote something similar in another language, I translated it to AutoIt, and with a few tests it seems it works ok. And I'm sure it's faster than WMI.

MsgBox(0, "Parent Process", _ProcessGetParent(@AutoItPID))

Func _ProcessGetParent($i_pid)
    Local Const $TH32CS_SNAPPROCESS = 0x00000002
    
    Local $a_tool_help = DllCall("Kernel32.dll", "long", "CreateToolhelp32Snapshot", "int", $TH32CS_SNAPPROCESS, "int", 0)
    If IsArray($a_tool_help) = 0 Or $a_tool_help[0] = -1 Then Return SetError(1, 0, $i_pid)
    
    Local $tagPROCESSENTRY32 = _
        DllStructCreate _
            ( _
                "dword dwsize;" & _
                "dword cntUsage;" & _
                "dword th32ProcessID;" & _
                "uint th32DefaultHeapID;" & _
                "dword th32ModuleID;" & _
                "dword cntThreads;" & _
                "dword th32ParentProcessID;" & _
                "long pcPriClassBase;" & _
                "dword dwFlags;" & _
                "char szExeFile[260]" _
            )
    DllStructSetData($tagPROCESSENTRY32, 1, DllStructGetSize($tagPROCESSENTRY32))
    
    Local $p_PROCESSENTRY32 = DllStructGetPtr($tagPROCESSENTRY32)
    
    Local $a_pfirst = DllCall("Kernel32.dll", "int", "Process32First", "long", $a_tool_help[0], "ptr", $p_PROCESSENTRY32)
    If IsArray($a_pfirst) = 0 Then Return SetError(2, 0, $i_pid)
    
    Local $a_pnext, $i_return = 0
    If DllStructGetData($tagPROCESSENTRY32, "th32ProcessID") = $i_pid Then
        $i_return = DllStructGetData($tagPROCESSENTRY32, "th32ParentProcessID")
        DllCall("Kernel32.dll", "int", "CloseHandle", "long", $a_tool_help[0])
        If $i_return Then Return $i_return
        Return $i_pid
    EndIf
    
    While 1
        $a_pnext = DLLCall("Kernel32.dll", "int", "Process32Next", "long", $a_tool_help[0], "ptr", $p_PROCESSENTRY32)
        If IsArray($a_pnext) And $a_pnext[0] = 0 Then ExitLoop
        If DllStructGetData($tagPROCESSENTRY32, "th32ProcessID") = $i_pid Then
            $i_return = DllStructGetData($tagPROCESSENTRY32, "th32ParentProcessID")
            If $i_return Then ExitLoop
            $i_return = $i_pid
            ExitLoop
        EndIf
    WEnd
    
    If $i_return = "" Then $i_return = $i_pid
    
    DllCall("Kernel32.dll", "int", "CloseHandle", "long", $a_tool_help[0])
    Return $i_return
EndFunc

Edit:

Had to edit code... I foresaw an issue with it.

Edited by SmOke_N
code would help huh? lol ...

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

Excellent work SmOke_N ;)

I didn't mentioned not to use WMI because of performance / security issues.

What about the amount of child processes when I know now my parent process?

Thanks,

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Excellent work SmOke_N ;)

I didn't mentioned not to use WMI because of performance / security issues.

What about the amount of child processes when I know now my parent process?

Thanks,

UEZ

I was working on that as well.

Without getting into a recursive nightmare, this will only get top level child processes:

#include <array.au3>
$a_children = _ProcessGetChildren(252)
_ArrayDisplay($a_children)

Func _ProcessGetChildren($i_pid) ; First level children processes only
    Local Const $TH32CS_SNAPPROCESS = 0x00000002
    
    Local $a_tool_help = DllCall("Kernel32.dll", "long", "CreateToolhelp32Snapshot", "int", $TH32CS_SNAPPROCESS, "int", 0)
    If IsArray($a_tool_help) = 0 Or $a_tool_help[0] = -1 Then Return SetError(1, 0, $i_pid)
    
    Local $tagPROCESSENTRY32 = _
        DllStructCreate _
            ( _
                "dword dwsize;" & _
                "dword cntUsage;" & _
                "dword th32ProcessID;" & _
                "uint th32DefaultHeapID;" & _
                "dword th32ModuleID;" & _
                "dword cntThreads;" & _
                "dword th32ParentProcessID;" & _
                "long pcPriClassBase;" & _
                "dword dwFlags;" & _
                "char szExeFile[260]" _
            )
    DllStructSetData($tagPROCESSENTRY32, 1, DllStructGetSize($tagPROCESSENTRY32))
    
    Local $p_PROCESSENTRY32 = DllStructGetPtr($tagPROCESSENTRY32)
    
    Local $a_pfirst = DllCall("Kernel32.dll", "int", "Process32First", "long", $a_tool_help[0], "ptr", $p_PROCESSENTRY32)
    If IsArray($a_pfirst) = 0 Then Return SetError(2, 0, $i_pid)
    
    Local $a_pnext, $a_children[11][2] = [[10]], $i_child_pid, $i_parent_pid, $i_add = 0
    $i_child_pid = DllStructGetData($tagPROCESSENTRY32, "th32ProcessID")
    If $i_child_pid <> $i_pid Then
        $i_parent_pid = DllStructGetData($tagPROCESSENTRY32, "th32ParentProcessID")
        If $i_parent_pid = $i_pid Then
            $i_add += 1
            $a_children[$i_add][0] = $i_child_pid
            $a_children[$i_add][1] = DllStructGetData($tagPROCESSENTRY32, "szExeFile")
        EndIf
    EndIf
    
    While 1
        $a_pnext = DLLCall("Kernel32.dll", "int", "Process32Next", "long", $a_tool_help[0], "ptr", $p_PROCESSENTRY32)
        If IsArray($a_pnext) And $a_pnext[0] = 0 Then ExitLoop
        $i_child_pid = DllStructGetData($tagPROCESSENTRY32, "th32ProcessID")
        If $i_child_pid <> $i_pid Then
            $i_parent_pid = DllStructGetData($tagPROCESSENTRY32, "th32ParentProcessID")
            If $i_parent_pid = $i_pid Then
                If $i_add = $a_children[0][0] Then
                    ReDim $a_children[$a_children[0][0] + 11][2]
                    $a_children[0][0] = $a_children[0][0] + 10
                EndIf
                $i_add += 1
                $a_children[$i_add][0] = $i_child_pid
                $a_children[$i_add][1] = DllStructGetData($tagPROCESSENTRY32, "szExeFile")
            EndIf
        EndIf
    WEnd
    
    If $i_add <> 0 Then 
        ReDim $a_children[$i_add + 1][2]
        $a_children[0][0] = $i_add
    EndIf
    
    DllCall("Kernel32.dll", "int", "CloseHandle", "long", $a_tool_help[0])
    If $i_add Then Return $a_children
    Return SetError(3, 0, 0)
EndFunc

Edit:

Turned the return into a 2 dimensional array... [n][0] will be the PID, [n][1] will be the name of the process.

If no array is returned, then that process does not have child processes.

Edit2:

Changed ReDim $a_children[$a_children[0][0] + 10][2] to ReDim $a_children[$a_children[0][0] + 11][2]

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

If you've already checked out the getting child processes, check it it now with the 2D array that includes the process name as well.


Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

I was working on that as well.

Without getting into a recursive nightmare, this will only get top level child processes:

...

Once again: Excellent work SmOke_N.

Now my screensaver closes properly when I select in 'settings window' another ss. ;)

Screensaver.au3 uses the ComboList check to close ss in 'settings window'.

My idea was that only one child process can run by rundll32.exe when selecting any ss.

Thanks a lot!

UEZ :D


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#7 ·  Posted (edited)

Thanks SmokeN - I'll probably use it.

Want to complete the order form:

; ==================================================================================================
; Name:     _ProcessGetChildren
; Purpose:  Get a list of top-level child processes
; Syntax:
;           _ProcessGetChildren($i_ParentPID)
; Returns:
;           Success:
;               If child processes ARE found ...
;                   Returns a two-dimensional array wherein ...
;                       $arr[n][0] = the PID of a child process
;                       $arr[n][1] = the name of that child process
;
;               If child processes are NOT found ...
;                   Returns 0
;
;           Failure:
;               The passed $i_ParentPID is returned unchanged; 
;               @error is set as follows ...
;                   1  - the first call to a function within "Kernel32.dll" failed.
;                   2  - the first call to a function within "Kernel32.dll" failed.
;
; Notes: 
;           If successful and no array is returned, then the passed process does not have child 
;               processes. 
;
;           #Region Test_harness
;               #include <array.au3>
;               Global $a_children = _ProcessGetChildren(252)
;               _ArrayDisplay($a_children)
;           #EndRegion
; Author:
;           SmokeN - August 16, 2008; Kudos to UEZ
; ==================================================================================================

Like, maybe this only works in Vista +

Edited by Squirrely1

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Thanks SmokeN - I'll probably use it.

Want to complete the order form:

; ==================================================================================================
; Name:     _ProcessGetChildren
; Purpose:  Get a list of top-level child processes
; Syntax:
;           _ProcessGetChildren($i_ParentPID)
; Returns:
;           Success:
;               If child processes ARE found ...
;                   Returns a two-dimensional array wherein ...
;                       $arr[n][0] = the PID of a child process
;                       $arr[n][1] = the name of that child process
;
;               If child processes are NOT found ...
;                   Returns 0
;
;           Failure:
;               The passed $i_ParentPID is returned unchanged; 
;               @error is set as follows ...
;                   1  - the first call to a function within "Kernel32.dll" failed.
;                   2  - the first call to a function within "Kernel32.dll" failed.
;
; Notes: 
;           If successful and no array is returned, then the passed process does not have child 
;               processes. 
;
;           #Region Test_harness
;               #include <array.au3>
;               Global $a_children = _ProcessGetChildren(252)
;               _ArrayDisplay($a_children)
;           #EndRegion
; Author:
;           SmokeN - August 16, 2008; Kudos to UEZ
; ==================================================================================================oÝ÷ Ûú®¢×¹Ú,笰ý§k÷®¦Ç«¾'²Ö­ç£ÐSZØZ¶uêå¢,~éçÈGb´[§rبuêÚºÚ"µÍÏOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOBÂÈ[Ý[Û[YNÔØÙÜÑÙ]Ú[[
BÈØÜ[Û]Y]H[^[Ü][Ú[ØÙÜÙÈÈ[Y]ÊN   ÌÍÚWÜYHØÙÜÈY[YYÙHØÙÜÈ[ÝHØ[ÈÝHÚ[ÈØÙÜÙÈÛHÈ][YJÊNÈÛÝXØÙÜÎÈ[Y[Ú[Û[^NÈÛVÌHÈHØÙÜÈYÙHÚ[ÈÛVÌWHÈHØÙÜÈ[YHÙHÚ[ÂÈÛZ[NÈÛ^HÂÈÜÈ
JNÜX]UÛÛ[ÌÛÚÝZ[YÈ
NØÙÜÌÌÝÈ]]ÜÊNÛSÚÙWÓ
ÛY[Ù[HÂÏOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

I can certainly see how this one might end up in Process.au3

It could probably find hidden processes - like ones left over from running those funky shareware screen savers? I see benchmarking utility is this thing, as well.

Well down, thou faithful and observant service station attendant, and...

Thanks again, cuz this is really Smoke_N ! ;)

I think UEZ might be a little confused about this thing though, because I don't see how it could be used to close your screensaver when you change the selection in the dropdown of the applet's Screen Saver tab when Windows closes only the GUI of your screensaver.

Edit 1: Oh - I get it - keep checking, and if your .scr process is no longer the child of the rundll32.exe pid, then exit.

Edited by Squirrely1

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

...

Edit 1: Oh - I get it - keep checking, and if your .scr process is no longer the child of the rundll32.exe pid, then exit.

That's not possible, because when you select another ss from ComboBox then rundll32.exe start the other ss and it becomes also a child process. That means that your ss must close when the amount of child processes is greater then 1.

Here an extract of my ss:

...
    Local $parent_PID = _ProcessGetParent(@AutoItPID)
    Local $child_PID
    While 1
        If Not WinExists($hWnd) Then Quit()
        $child_PID = _ProcessGetChildren($parent_PID)
        If $child_PID[0] > 1 Then Quit() ;if another screensaver is selected in ComboBox close ss
        Line_Color()
        Draw()
    WEnd
...

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Thanks for all your attention my behalf, UEZ, but I see a few problems with your function ...

#1: _ProcessGetChildren returns a two-dimensional array when it even returns an array.

#2: I see nothing in the documentation for _ProcessGetChildren even that $aArray[0][0] returns the number of child processes.

#3: Couldn't it be true that when some other screensaver is selected in the combo, that your screensaver's process keeps running but stops being a child, while the newly selected one begins being a child, thereby keeping the number of child processes the same?

Thanks again from the USA (no that country is nowhere in China). ;)

Edited by Squirrely1

Das Häschen benutzt Radar

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

Thanks for all your attention my behalf, UEZ, but I see a few problems with your function ...

#1: _ProcessGetChildren returns a two-dimensional array when it even returns an array.

#2: I see nothing in the documentation for _ProcessGetChildren even that $aArray[0][0] returns the number of child processes.

#3: Couldn't it be true that when some other screensaver is selected in the combo, that your screensaver's process keeps running but stops being a child, while the newly selected one begins being a child, thereby keeping the number of child processes the same?

Thanks again from the USA - no, that country is nowhere in China. ;)

Oops, I forgotten to mention that I used the versions with 1D array before it was edited.

It is working: click here for scr file + source code

Source code will be available when I think that it can be published :D

Greetings from the Boot Camp near Frankfurt / Germany

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#2: I see nothing in the documentation for _ProcessGetChildren even that $aArray[0][0] returns the number of child processes.

That's my fault, I did make [0][0] contain the number of child processes found. I was trying to keep it similar to the ProcessList() function.

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Share this post


Link to post
Share on other sites

well, im not really sure, but seems like "ProcessGetChildren" does not work in Windows 7 x64 - can anyone verify?

or maybe even someone already has a workaround for this?

Share this post


Link to post
Share on other sites

well, im not really sure, but seems like "ProcessGetChildren" does not work in Windows 7 x64 - can anyone verify?

or maybe even someone already has a workaround for this?

It is not running in native x64 mode (F5 in SciTE)! You have to compile and running x32 mode.

#AutoIt3Wrapper_UseX64=n
#include <array.au3>
$explorer = ProcessList("explorer.exe")

$a_children = _ProcessGetChildren($explorer[1][1])
_ArrayDisplay($a_children)

Func _ProcessGetChildren($i_pid) ; First level children processes only
    Local Const $TH32CS_SNAPPROCESS = 0x00000002

    Local $a_tool_help = DllCall("Kernel32.dll", "long", "CreateToolhelp32Snapshot", "int", $TH32CS_SNAPPROCESS, "int", 0)
    If IsArray($a_tool_help) = 0 Or $a_tool_help[0] = -1 Then Return SetError(1, 0, $i_pid)

    Local $tagPROCESSENTRY32 = _
    DllStructCreate _
    ( _
    "dword dwsize;" & _
    "dword cntUsage;" & _
    "dword th32ProcessID;" & _
    "uint th32DefaultHeapID;" & _
    "dword th32ModuleID;" & _
    "dword cntThreads;" & _
    "dword th32ParentProcessID;" & _
    "long pcPriClassBase;" & _
    "dword dwFlags;" & _
    "char szExeFile[260]" _
    )
    DllStructSetData($tagPROCESSENTRY32, 1, DllStructGetSize($tagPROCESSENTRY32))

    Local $p_PROCESSENTRY32 = DllStructGetPtr($tagPROCESSENTRY32)

    Local $a_pfirst = DllCall("Kernel32.dll", "int", "Process32First", "long", $a_tool_help[0], "ptr", $p_PROCESSENTRY32)
    If IsArray($a_pfirst) = 0 Then Return SetError(2, 0, $i_pid)

    Local $a_pnext, $a_children[11][2] = [[10]], $i_child_pid, $i_parent_pid, $i_add = 0
    $i_child_pid = DllStructGetData($tagPROCESSENTRY32, "th32ProcessID")
    If $i_child_pid <> $i_pid Then
    $i_parent_pid = DllStructGetData($tagPROCESSENTRY32, "th32ParentProcessID")
    If $i_parent_pid = $i_pid Then
    $i_add += 1
    $a_children[$i_add][0] = $i_child_pid
    $a_children[$i_add][1] = DllStructGetData($tagPROCESSENTRY32, "szExeFile")
    EndIf
    EndIf

    While 1
    $a_pnext = DLLCall("Kernel32.dll", "int", "Process32Next", "long", $a_tool_help[0], "ptr", $p_PROCESSENTRY32)
    If IsArray($a_pnext) And $a_pnext[0] = 0 Then ExitLoop
    $i_child_pid = DllStructGetData($tagPROCESSENTRY32, "th32ProcessID")
    If $i_child_pid <> $i_pid Then
    $i_parent_pid = DllStructGetData($tagPROCESSENTRY32, "th32ParentProcessID")
    If $i_parent_pid = $i_pid Then
    If $i_add = $a_children[0][0] Then
    ReDim $a_children[$a_children[0][0] + 11][2]
    $a_children[0][0] = $a_children[0][0] + 10
    EndIf
    $i_add += 1
    $a_children[$i_add][0] = $i_child_pid
    $a_children[$i_add][1] = DllStructGetData($tagPROCESSENTRY32, "szExeFile")
    EndIf
    EndIf
    WEnd

    If $i_add <> 0 Then
    ReDim $a_children[$i_add + 1][2]
    $a_children[0][0] = $i_add
    EndIf

    DllCall("Kernel32.dll", "int", "CloseHandle", "long", $a_tool_help[0])
    If $i_add Then Return $a_children
    Return SetError(3, 0, 0)
EndFunc

UEZ


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

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