Jump to content

Find non-autoit handle from multi istance of the same program


Recommended Posts

ciao

I have a Delphi compiled program that I use for work and I can read some logs with this function:

Func __ReadExternalListBox()
    Local $hListBox, $iItemCount
    $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]")
    ConsoleWrite("$hListBox = " & $hListBox & @CRLF)
    $iItemCount = _GUICtrlListBox_GetCount($hListBox)
    For $i = $iStart To $iItemCount - 1
        ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF)
    Next
EndFunc   ;==>__ReadExternalListBox

I can find pid and full path of the process.

The problem is when I must open another process: I can't read the new ListBox because the title of the window to read is the same and the function 

$hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]")

return me only one handle.

With Autoinfo I can read handle: is, for this instance, 0x0001099C and is $hListBox

image.png.67d49275530b8cd0b0dde1491851e7c1.png

But I need to automize some function and I can't always change in runtime this values.

Ideas? Is there e method to read this title windows associated to a determined pid?

PS:

I don't need the handle from the pid windows application, but from its control

if I use

_WinAPI_EnumProcessWindows()

the function return me window handle, not Control handle

Iimage.png.29ded61794b5df283e9e6e8b8d8f2013.png

In this case Windows Handle is 0x001007DA but I need Control Handle that is 0x0001099C

Thankyou

Marco

Edited by marcoauto
Link to comment
Share on other sites

3 minutes ago, Danp2 said:

It sounds like you already know the PID of the target application. I would use this with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window. Then pass this handle as the first parameter to ControlGetHandle.

It don't works. The TlistBox is not in the main window. If I use Autoit Windows Info (see pictures above) then you can see that handle that I need is in "control tab" 😔

Link to comment
Share on other sites

the problem that i don't use pid to locate windows. I use "title". I know that "Software Setup" is the Window Title where TListBox is in. I found with Autoit Info. I use title and class with th function that i wrote in my first post:

Func __ReadExternalListBox()
    Local $hListBox, $iItemCount
    $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]")
    ConsoleWrite("$hListBox = " & $hListBox & @CRLF)
    $iItemCount = _GUICtrlListBox_GetCount($hListBox)
    For $i = $iStart To $iItemCount - 1
        ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF)
    Next
EndFunc   ;==>__ReadExternalListBox

I know the process pid because I use a run process to start it,  but i don't need for read TListBox

$pid = Run(@ComSpec & ' /c programmDelphi.exe', $sPercorsoEncoder, @SW_HIDE)

The problem is when I need to start a second, or third programDelphi.exe. I could knows their pids, but title is the same for all istances. I can associate title with pid. 

Sorry but my english is not very good. I don't know if I can explain my problem

Thanks

Marco

Link to comment
Share on other sites

It’s a pascal based control I doubt AutoIt can natively manipulate it. Post the code

 

Long as it’s win32 control than AutoIt should work 

Edited by Earthshine

My resources are limited. You must ask the right questions

 

Link to comment
Share on other sites

39 minutes ago, marcoauto said:

I know the process pid because I use a run process to start it,  but i don't need for read TListBox

You do need it if you want to be sure that you are accessing the window from the correct instance of the application. I previously tried to explain how you could do this, but it seems that you concluded that it wouldn't work without even attempting it. 😒

16 minutes ago, Earthshine said:

It’s a pascal based control I doubt AutoIt can natively manipulate it.

It sounds like he had it working, just not for other instances of the app. FWIW, I have been able to access some Delphi controls in the past.

Link to comment
Share on other sites

6 hours ago, Earthshine said:

It’s a pascal based control I doubt AutoIt can natively manipulate it. Post the code

 

Long as it’s win32 control than AutoIt should work 

hi,

hi, the code I use is the one I wrote in the first post. And it works perfectly. The problem is when opening an additional instance of the program. I re-write here:

Func __ReadExternalListBox()
    Local $hListBox, $iItemCount
    $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]")
    ConsoleWrite("$hListBox = " & $hListBox & @CRLF)
    $iItemCount = _GUICtrlListBox_GetCount($hListBox)
    For $i = $iStart To $iItemCount - 1
        ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF)
    Next
EndFunc   ;==>__ReadExternalListBox

for the moment my program is very basic. Before continuing to develop it I wanted to figure out if I could use it with multiple instances, but the above code works great. I read everything I need from the program compiled in Delphi.

Link to comment
Share on other sites

6 hours ago, Danp2 said:

You do need it if you want to be sure that you are accessing the window from the correct instance of the application. I previously tried to explain how you could do this, but it seems that you concluded that it wouldn't work without even attempting it. 😒

It sounds like he had it working, just not for other instances of the app. FWIW, I have been able to access some Delphi controls in the past.

I think my English is worse than I thought ... I tried as you said with the _WinAPI_EnumProcessWindows () function but, as I wrote in the first post, it doesn't work! Or at least, what comes back to me isn't what I need. In the array I have 3 return values: the first for "TSetUpForm", the second for "TMainForm", and third for "TApplication" but I need the handle associated with the TListBox class: INSTANCE: 1

With ths function I read all I need, but only if I one only instance of running program:

Func __ReadExternalListBox()
    Local $hListBox, $iItemCount
    $hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]")
    ConsoleWrite("$hListBox = " & $hListBox & @CRLF)
    $iItemCount = _GUICtrlListBox_GetCount($hListBox)
    For $i = $iStart To $iItemCount - 1
        ConsoleWrite(GUICtrlListBox_GetText($hListBox,$i) & @CRLF)
    Next
EndFunc   ;==>__ReadExternalListBox

Now, I ran the function. Program PID is 10248

if I use 

_arraydisplay(_WinAPI_EnumProcessWindows(10248))

the array is

image.png.fe6aa7e373dfe00ce3cfa3595b98e57e.png

but 

$hListBox = ControlGetHandle("Software Setup", "", "[CLASS:TListBox; INSTANCE:1]")
 ConsoleWrite("$hListBox = " & $hListBox & @CRLF)

$hListBox = 0x00540406

I don't need this:

image.png.b3076c348479e729aba31d7d7a3ad042.png

but I need this:

image.png.373fb8a305470b8548ae129754c67095.png

if I use ControlGetHandle I read everything, but in the case of multiple open instances it returns only one and I don't know how to read the value of that handle associated with that particular pid, since I find the value through the title which is obviously identical for all instances of the program

thank you all

Marco

image.png

Link to comment
Share on other sites

@marcoautoYour English is fine. Maybe I didn't properly explain the steps needed, so let's try again --

  • Get the PID of the desired instance. You already have this from your Run() command.
  • Use this PID with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window.
    • Store the result into an array
    • Locate the desired row with "TSetupForm" in the second column
    • Grab the window handle from the first column
  • Now that you have the correct window handle, use it in conjunction with ControlGetHandle to obtain the desired control handle.

Your code would look something like this --

$pid = Run(@ComSpec & ' /c programmDelphi.exe', $sPercorsoEncoder, @SW_HIDE)
$aWindows = _WinAPI_EnumProcessWindows($pid)
$iIndex = _ArraySearch($aWindows, "TSetupForm", 0, 0, 0, 0, 1, 1)
$hWnd = $aWindows[$iIndex][0]
$hListBox = ControlGetHandle($hWnd, "", "[CLASS:TListBox; INSTANCE:1]")

To be clear, the above code is untested, needs error handling, etc. 😉

Link to comment
Share on other sites

10 hours ago, Danp2 said:

@marcoautoYour English is fine. Maybe I didn't properly explain the steps needed, so let's try again --

  • Get the PID of the desired instance. You already have this from your Run() command.
  • Use this PID with _WinAPI_EnumProcessWindows() to obtain the handle of the desired window.
    • Store the result into an array
    • Locate the desired row with "TSetupForm" in the second column
    • Grab the window handle from the first column
  • Now that you have the correct window handle, use it in conjunction with ControlGetHandle to obtain the desired control handle.

Your code would look something like this --

$pid = Run(@ComSpec & ' /c programmDelphi.exe', $sPercorsoEncoder, @SW_HIDE)
$aWindows = _WinAPI_EnumProcessWindows($pid)
$iIndex = _ArraySearch($aWindows, "TSetupForm", 0, 0, 0, 0, 1, 1)
$hWnd = $aWindows[$iIndex][0]
$hListBox = ControlGetHandle($hWnd, "", "[CLASS:TListBox; INSTANCE:1]")

To be clear, the above code is untested, needs error handling, etc. 😉

hi, thanks for your time and your help. I can't read handle I need. For now I have a workaround for my problem using a different program, but I'll continue to investigate and try. Thankyou again

Link to comment
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
 Share

×
×
  • Create New...