Sign in to follow this  
Followers 0
michaelslamet

How to Know PID in this case

27 posts in this topic

I've a AutoIT command line application that call another (not AutoIT) application using runwait(@comspec & ' /c " $command)

This other application will open Internet Explorer.

I would like my AutoIT script know the PID number of the Internet Explorer openned by this external application.

How to know this? or it's not possible?

Share this post


Link to post
Share on other sites



Use ProcessList before and after you start the "another (not AutoIT) application".

The difference will be the IE processes extra.

 

Wow, thanks JohnOne, great idea!

Is there any other way I can try?

Share this post


Link to post
Share on other sites

another way:

#include <IE.au3>
$oIE = _IEAttach("the title")
$hwnd = _IEPropertyGet($oIE, "hwnd")

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

 

another way:

#include <IE.au3>
$oIE = _IEAttach("the title")
$hwnd = _IEPropertyGet($oIE, "hwnd")

 

EDIT:

sorry, I forgot a piece

#include <IE.au3>
$oIE = _IEAttach("the title")
; $hwnd = _IEPropertyGet($oIE, "hwnd")
Local $pid = WinGetProcess(_IEPropertyGet($oIE, "hwnd"))
Edited by Pincopanco

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

@Pincopanco: thanks, but I call the internet explorer from other application (not AutoIT), please read my original post :)

Share this post


Link to post
Share on other sites

but once ixplore is running, you can _IEAttch() to it regardless of how you have started ....... (or not?)
this script should give you back the PID of iexplore even if it is started in any way different from autoit

am I wrong?

p.s.

of course I assume that you change the string "the title" in listing accordingly to Your searched web page


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

What is there are several windows with the same name and same url?

 

that's true.....

well, I can always close all the other windows and leave only one opened... :P

p.s

but the same problem does not arise also with WinList()?


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

$PID = Run(@ComSpec & ' /c calc.exe')
;Do something with PID here
ProcessWaitClose($PID)

 

but michaelslamet used runwait(), not run()

Edited by Pincopanco

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

0xdefea7's post makes more sense than anything else posted, after all using RunWait means that the script won't continue until the process is closed, so having a PID of a program that's not running any longer is pretty much pointless. You can't do anything with the information, and I'm pretty sure you won't get any information to begin with.

1 person likes this

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

0xdefea7's post makes more sense than anything else posted, after all using RunWait means that the script won't continue until the process is closed, so having a PID of a program that's not running any longer is pretty much pointless. You can't do anything with the information, and I'm pretty sure you won't get any information to begin with.

 

ok, but....

the pid that you get from run() is not the pid of the explorer window spawned in turn by the $command inside run(), I think that the two PID are different


small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#15 ·  Posted (edited)

0xdefea7's post makes more sense than anything else posted, after all using RunWait means that the script won't continue until the process is closed, so having a PID of a program that's not running any longer is pretty much pointless. You can't do anything with the information, and I'm pretty sure you won't get any information to begin with.

 

 

It still will not get the PID of the newly spawned IE.

OP Runs exe (not autoit exe) the non autoit exe starts windows explorer.

No amount of run or runwait is going to give you the IE PID

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

#16 ·  Posted (edited)

You can get a list of IE processes, then check their Parent Process ID's.  This means you would have to use 'Run' instead of RunWait, so that you have the Parent ID.  Then you can establish from there which children were created.

I have a few functions in my Processes UDF that can be used to get this info (see signature):

_ProcessListEx()   - will return parent process ID's as part of its info

_ProcessGetChildren() - gets a list of child processes created by a PRocess ID

_ProcessGetParent() - gets the parent Process ID

and

_ProcessUDGetParentPID() - quicker, gets the parent Process ID from a Process handle (requires _WinAPI_OpenProcess etc)

*edit: I should note that you'll need to go 'up' two levels to find the 'Grandparent'.. or down two levels..

2nd edit: You'd need to have that interim process to be alive for this all to work.  Maybe its best to just do 'ProcessList' twice and compare the arrays... unless IE just adds an extra tab instead of maintaining a new process.. bleh..  you need a better method than all this

Edited by Ascend4nt

Share this post


Link to post
Share on other sites

#17 ·  Posted (edited)

well, f*k me, I guess I like a good challenge.  Here's a UDF for finding processes that started after a given time point:

; ========================================================================================================
; <_ProcessListAfterTimePoint.au3>
;
; Functions to get an array of processes that started after a given time point
; Example included displays array of processes
;
; Functions:
;    _WinTime_GetSystemTimeAsLocalFileTime()  ; Gets current time as 64-bit FILETIME (_WinTimeFunctions UDF)
;    _ProcessListAfterTime()    ; Gets list of processes after a certain timepoint (as FILETIME)
;
; Author: Ascend4nt
; ========================================================================================================
#include <WinAPI.au3>    ; ProcessOpen/CloseHandle

; ==============================================================================================
; Func _WinTime_GetSystemTimeAsLocalFileTime()
;
; Function to grab the current system time as 64bit Local FileTime (not UTC)
; (from _WinTimeFunctions UDF)
;
; Return:
;    Success: 64-bit value representing the UTC-based FileTime
;    Failure: -1, with @error set:
;        @error = 2 = DLL Call error, @extended = actual DLLCall error code
;
; Author: Ascend4nt
; ==============================================================================================
Func _WinTime_GetSystemTimeAsLocalFileTime()
    Local $aRet=DllCall("kernel32.dll","none","GetSystemTimeAsFileTime","uint64*",0)
    If @error Then Return SetError(2,@error,-1)
    Return $aRet[1]
EndFunc

; ==============================================================================================
; Func _ProcessListAfterTime($nSysTime, $vProcFilter = "")
;
; Returns an array of Processes that started after a given time point (as FILETIME)
;
; $nSysTime = a 64-bit FILETIME value (see GetSystemTimeAsFileTime) to use
;             as the starting point
;
; $vProcFilter = Process name filter ("calc.exe") or "" for ALL processes
;
; Returns:
;  Success: An array of processes in the same form as ProcessList:
;    [0][0] = # of processes
;    [i][0] = Process name
;    [i][1] = Process ID #
;
; Failure: "" with @error set (only happens if ProcessList() itself fails)
;
;
; Author: Ascend4nt
; ==============================================================================================

Func _ProcessListAfterTime($nSysTime, $vProcFilter = "")
    Local $aProcList, $aFoundList, $nFound
    Local $iAccess, $hProcess

    If $vProcFilter = "" Then
        $aProcList = ProcessList()
    Else
        $aProcList = ProcessList($vProcFilter)
    EndIf
    If @error Then Return SetError(@error,0,"")

    ; XP, XPe, 2000, or 2003? - Affects process access requirement
    If StringRegExp(@OSVersion,"_(XP|200(0|3))") Then
        $iAccess = 0x0400    ; PROCESS_QUERY_INFORMATION
    Else
        $iAccess = 0x1000    ; PROCESS_QUERY_LIMITED_INFORMATION
    EndIf

    Dim $aFoundList[$aProcList[0][0]+1][2]
    $nFound = 0

    For $i = 1 To $aProcList[0][0]
        $hProcess = _WinAPI_OpenProcess($iAccess, False, $aProcList[$i][1])
        $aRet = DllCall("kernel32.dll", "bool", "GetProcessTimes", "handle", $hProcess, "uint64*", 0, "uint64*", 0, "uint64*", 0, "uint64*", 0)
        If Not @error And $aRet[0] And $aRet[2] > $nSysTime Then
            ConsoleWrite("Found process that started after timepoint: " & $aProcList[$i][0]&", PID #" & $aProcList[$i][1] & @CRLF)
            $nFound += 1
            $aFoundList[$nFound][0] = $aProcList[$i][0]
            $aFoundList[$nFound][1] = $aProcList[$i][1]
        EndIf
        _WinAPI_CloseHandle($hProcess)
    Next
    $aFoundList[0][0] = $nFound

    ReDim $aFoundList[$nFound + 1][2]
    Return $aFoundList
EndFunc


; --- EXAMPLE USAGE ---

#include <Array.au3>
Local $nSysTime, $aProcList

$nSysTime = _WinTime_GetSystemTimeAsLocalFileTime()
Sleep(10)   ; Some systems may need a small sleep (see MichaelIslamet's posts)
Run("calc.exe")
Run("notepad.exe")
Sleep(500)

$aProcList = _ProcessListAfterTime($nSysTime)
_ArrayDisplay($aProcList, "Processes that started after start point")

In michaelslamet's case, call it like _ProcessListAfterTime($nSysTime, "iexplore.exe").

*edit: Added Sleep(10) after getting the System Time.  May or may not be system-specific issue (see >MichaelIslamet's post)

Edited by Ascend4nt
2 people like this

Share this post


Link to post
Share on other sites

beautiful solutions Ascend4ant, and also very instructive!

also nice the _ProcessListAfterTime!

following the advice of Mr. Ascend4ant in post # 16, his wonderful UDF, and if it is allowed to use the run () instead RunWait () should then work even these simple few lines (a bit botched):
 

#include <array.au3>
#include <_ProcessListFunctions.au3>    ; <-- download from Ascend4nt signature
                                        ; https://sites.google.com/site/ascend4ntscode/processfunctions

$father_pid = run(@comspec & ' /c ' & $command) ; pid of father

Sleep(1000) ; give time to spawn childs or _ProcessGetChildren will not find them

$childs = _ProcessGetChildren($father_pid)  ; list of child(s) processes spawned by $father
                                            ; (in this case should be only 1)
; Return:
;       [0][0] = # of Child Processes (0 = none found)
;       [$i][0] = Process Name
;       [$i][1] = Process ID #
;       [$i][2] = Parent Process ID #
;       [$i][3] = Thread Count
;       [$i][4] = Threads Base Priority

$child_pid = $childs [1][1] ; Process ID # of the (single) child
                            ; $out[1][2] should be = $fatherpid

$nephews = _ProcessGetChildren($child_pid)  ; list of nephew(s) processes spawned by $child
                                            ; should be the iexplore.exe (?)

$nephew_pid = $nephews [1][1] ; <-- this should be the searched PID

MsgBox(0,"",$nephew_pid)
1 person likes this

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Share this post


Link to post
Share on other sites

#20 ·  Posted (edited)

Thought I'd put up what I was banging on about (for reference)

But I don't even think it worked  :rolleyes:

#include <Array.au3>

Opt("WinTitleMatchMode", 2)
$aBefore = GetWinHandles()
Run(@ProgramFilesDir & "\internet explorer\iexplore.exe")
Sleep(2000)
WinMinimizeAll()
$after = GetWinHandles()

For $i = 0 To UBound($after) - 1
    $Testing = hWndInArray($aBefore, $after[$i])
    If $Testing Then
        WinSetState($Testing, "", @SW_RESTORE)
        GetPid($Testing)
        Exit
    EndIf
Next

Exit

Func GetPid($hwnd)
    $PID = DllStructCreate("int")
    $aCall = DllCall("user32.dll", "int", "GetWindowThreadProcessId", "hwnd", HWnd($hwnd), "dword*", DllStructGetPtr($PID))
    MsgBox(0,"PID", $aCall[2])
EndFunc

Func hWndInArray(ByRef $aArray, $hWnd)
    For $i = 0 To UBound($aArray) - 1
        If $hWnd = $aArray[$i] Then
            Return 0
        EndIf
    Next
    Return $hWnd
EndFunc   ;==>hWndInArray

Func GetWinHandles()
    $sIndex = ""
    $WindowCount = 0
    $aIEWindows = WinList("Windows Internet Explorer")
    For $i = 1 To UBound($aIEWindows) - 1
        $winstate = WinGetState($aIEWindows[$i][1])
        If BitAND($winstate, 2) Then
            $WindowCount += 1
            $sIndex &= $i
        EndIf
    Next
    Local $aOriginalWindows[$WindowCount]
    $aLocalArray = StringSplit($sIndex, "", 3)
    For $i = 0 To UBound($aLocalArray) - 1
        $aLocalArray[$i] = $aIEWindows[$aLocalArray[$i]][1]
    Next
    Return $aLocalArray
EndFunc   ;==>GetWinHandles
Edited by JohnOne
1 person likes this

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

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