Jump to content

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


Recommended Posts

Posted (edited)

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 post
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 post
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 post
Share on other sites
Posted (edited)

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 post
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 post
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 post
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 post
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 post
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 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.

  • Similar Content

    • By XGamerGuide
      I'm trying to call WinList() with a handle. That should be possible:
      But I only get back an 2d array that looks like this:
      ---------
      0 |
      (That means no window was found.)
      It's not the window or the handle. When I call other functions like WinExists() or WinGetHandle() it works.
      Is it because of me, the description in the reference or because of Autoit who makes a mistake?
      No, because of the rest of my program I don't want to use WinGetTitle() because the format of WinList() has to be kept. Alternatively, I could create a 2d array myself, but it should also work with WinList() ... I hope.
    • By nacerbaaziz
      hello sirs, please i created a tool witch get the focused control in a window and play a audio file linked with this controls
      e.g buttons, checkBoxes, radios, comboboxes, and others
      i know that their is a function that give us the control focus but it return the classNN
      i want to get the class name to use it with a switch and
      because their are more than class e.g button tbutton timagebutton tnewButton...
      please can any one help me to get the class name not the classnn
      thanks in advance
    • By rudi
      Hello,
      Either drag drop the opened file on the server and the temp file, Aut2Exe could not copy to the destination file, as that one is opened, to the edits of this GUI, or take the Aut2Exe error message line to your clipboard, the line will be split automatically.
      This script does not check
      For the required rights to the destination folder (to close open file handles) for correct input Use either clipboard (Aut2Exe message), drag & drop, or copy the full paths of source and destination file *IN ONE* (don't type, if you want to do so, modify the script, for me it's fine this way ;-)  
      Example Error Message:
      !>11:19:15 Problem copying file from: C:\Users\UserName\AppData\Local\AutoIt v3\Aut2exe\~AU98E6.tmp.exe To :z:\MyAutoitExeForTheUsers.exe
      #include <GUIConstantsEx.au3> #include <NetShare.au3> #include <WindowsConstants.au3> #include <Array.au3> #include <EditConstants.au3> ; Enumerate open files on the server $DragDropOpenFile = "<drag drop the opened file on a server share here>" $DragDropNewFile = "<drag drop the file supposed to replace the above one here>" $NewFile = "" $Gui_h = 250 $Gui_w = 800 $vDist = 7 ; GUICreate($GuiTitle, $w, $h, @DesktopWidth - $w - 100, @DesktopHeight - $h - 60, -1, $WS_EX_ACCEPTFILES) ; generally enable drag-drop for files into other GUI controls $myGui = GUICreate("Tool to forcibly close & replace open files on server shares", $Gui_w, $Gui_h, 100, 100, -1, $WS_EX_ACCEPTFILES) $InputFileToClose = GUICtrlCreateInput($DragDropOpenFile, 20, $vDist, $Gui_w - 40, 20) GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; allow drag-droping files for this control, $InputFile Opt("Guicoordmode", 2) $InputFileNew = GUICtrlCreateInput($DragDropNewFile, -1, $vDist) GUICtrlSetState(-1, $GUI_DROPACCEPTED) ; allow drag-droping files for this control, $InputFile GUICtrlSetState(-1, $GUI_DISABLE) $lServer = GUICtrlCreateLabel("<server>", -1, $vDist) $lShare = GUICtrlCreateLabel("<share-mapping>", -1, $vDist) $lPath = GUICtrlCreateLabel("<sub-path>", -1, $vDist) $lFile = GUICtrlCreateLabel("<file>", -1, $vDist) $doit = GUICtrlCreateButton("Search and close for open file handles", -1, $vDist) GUICtrlSetState(-1, $GUI_DISABLE) $exit = GUICtrlCreateButton("Cancel", -1, $vDist) GUISetState() $FN = False $FNnew = "" $FNmatch = False $ToolTitle = "" $ToolTxt = "" $RegExA2E = "(?i)^(?:.*?Problem copying file from: )(.*?)(?: To :)(.*$)" ; $1 = compiled local TEMP file, $2 = not replacable destination file ; Examle Replacement failed output: !>11:19:15 Problem copying file from: C:\Users\USERNAME\AppData\Local\AutoIt v3\Aut2exe\~AU98E6.tmp.exe To :z:\MyAutoitExeForTheUsers.exe While 1 $Clip = ClipGet() If StringRegExp($Clip, $RegExA2E) Then $Src = StringRegExpReplace($Clip, $RegExA2E, "$2") GUICtrlSetData($InputFileToClose, $Src) $Dst = StringRegExpReplace($Clip, $RegExA2E, "$1") GUICtrlSetData($InputFileNew, $Dst) EndIf $input = GUICtrlRead($InputFileToClose) If $input <> $DragDropOpenFile Then ; da wurde was reingezogen $DragDropOpenFile = $input If StringLeft($input, 2) = "\\" Then $Type = "UNC" $ServerShareUNC = StringLeft($input, StringInStr($input, "\", 0, 4) - 1) $fRelPathFN = StringReplace($input, $ServerShareUNC, "") $fPath = StringLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) $FN = StringTrimLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) ElseIf StringMid($input, 2, 1) = ":" Then ; Pfad mit Laufwerksbuchstabe, evtl. Netzwerk Mapping (erforderlich) $drive = StringLeft($input, 2) $Type = DriveGetType($drive) If $Type = "Network" Then $ServerShareUNC = DriveMapGet($drive) $foo = StringReplace($input, $drive, $ServerShareUNC) ; Laufwerkspfad in UNC Pfad umwandeln $fRelPathFN = StringReplace($foo, $ServerShareUNC, "") $fPath = StringLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) $FN = StringTrimLeft($fRelPathFN, StringInStr($fRelPathFN, "\", 0, -1)) Else MsgBox(48, @ScriptLineNumber, "This script can *ONLY* close remotely handles for files open on server shares!" & @CRLF & _ $input & @CRLF & _ $drive & " = " & $Type) ContinueLoop 2 EndIf EndIf $Server = StringLeft($ServerShareUNC, StringInStr($ServerShareUNC, "\", 0, 3) - 1) $Share = StringTrimLeft($ServerShareUNC, StringInStr($ServerShareUNC, "\", 0, 3) - 1) GUICtrlSetData($lServer,"Server = '" & $Server& "'") GUICtrlSetData($lShare, "Mapping = '" & $Share & "'") GUICtrlSetData($lPath, "SubPath = '" &$fPath & "'") GUICtrlSetData($lFile, "FileName= '" & $FN &"'") GUICtrlSetState($doit, $GUI_ENABLE) GUICtrlSetState($InputFileNew, $GUI_ENABLE) EndIf If $NewFile <> GUICtrlRead($InputFileNew) Then $NewFile = GUICtrlRead($InputFileNew) If $NewFile <> $DragDropNewFile Then If StringInStr($NewFile, $DragDropNewFile) Then $NewFile = StringReplace($NewFile, $DragDropNewFile, "") GUICtrlSetData($InputFileNew, $NewFile) EndIf $FNnew = StringTrimLeft($NewFile, StringInStr($NewFile, "\", 0, -1)) If $FN = $FNnew Then If $FNmatch = False Then $FNmatch = True GUICtrlSetData($doit, "Search for & Close open file handles, then replace file") EndIf Else If $FNmatch Then $FNmatch = False GUICtrlSetData($doit, "Search for & Close open file handles, then replace file") GUICtrlSetData($InputFileNew, $DragDropNewFile) EndIf EndIf EndIf EndIf Switch GUIGetMsg() Case $exit, $GUI_EVENT_CLOSE GUIDelete($myGui) Exit Case $doit AbArbeiten($Server, $Share, $fPath, $FN) EndSwitch WEnd Func AbArbeiten($_Srv, $_Shr, $_fPth, $_fNme) Local $iID = 0 Local $iRights = 1 Local $iLckCount = 2 Local $iFPFN = 3 Local $iUser = 4 ConsoleWrite($_fPth & $_fNme & @CRLF) Local $aFile = _Net_Share_FileEnum($_Srv) If IsArray($aFile) Then ; _ArrayDisplay($aFile) Local $x $ToolTxt = "Open File Handles:" $ToolTitle = "Handles to be checked total: " & $aFile[0][0] UpdateToolTip() AdlibRegister(UpdateToolTip, 1000) For $x = $aFile[0][0] To 1 Step -1 $ToolTitle = $x & " handles remaining for checking..." If Not StringInStr($aFile[$x][$iFPFN], $_fPth & $_fNme) Then ; ConsoleWrite("Nix Enthalten in: " & $aFile[$x][$iFPFN] & @CRLF) _ArrayDelete($aFile, $x) Else $ToolTxt &= @CRLF & $aFile[$x][$iFPFN] & ", User = " & $aFile[$x][$iUser] ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $ToolTxt = ' & $ToolTxt & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console EndIf Next $aFile[0][0] = UBound($aFile) - 1 _ArraySort($aFile, 0, 1, 0, $iUser) ; _ArrayDisplay($aFile, $aFile[0][0] & " FileLocks found.") If $aFile[0][0] = 0 Then $ToolTitle = "Done, no open file handles were found" $ToolTxt &= @CRLF & ", no handles to be closed for this file!" Sleep(2000) $ToolTxt = "" ReplaceFile() Else $ToolTitle = $aFile[0][0] & " open file handles were found..." $CloseErr = 0 For $x = 1 To $aFile[0][0] If _Net_Share_FileClose($Server, $aFile[$x][$iID]) Then $ToolTxt &= @CRLF & @TAB & "Handle closed: " & $aFile[$x][$iID] Else $ToolTxt &= @CRLF & "ERROR: Handle Close Failed! --> " & $aFile[$x][$iFPFN] & ", User = " & $aFile[$x][$iUser] $CloseErr += 1 EndIf Next ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $CloseErr = ' & $CloseErr & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console If $CloseErr = 0 Then $ToolTitle = "All found open file handles could be closed." ReplaceFile() Else $ToolTitle = $CloseErr & " Handles could *NOT* be closed!" Sleep(2000) EndIf Sleep(1000) $ToolTxt = "" $ToolTitle = "" EndIf Else MsgBox(0, "not an array", $aFile & @CRLF & @error & @CRLF & @extended & @CRLF & _ "Unable to retrieve the array of open file handles for " & $Share) EndIf EndFunc ;==>AbArbeiten Func UpdateToolTip() ToolTip($ToolTxt, MouseGetPos(0) + 20, MouseGetPos(1) + 20, $ToolTitle) ; ConsoleWrite( $ToolTxt & @CRLF & $ToolTitle & @CRLF & "-------------------" & @CRLF) EndFunc ;==>UpdateToolTip Func ReplaceFile() If FileExists($NewFile) Then If FileCopy($NewFile, $input, 1 + 8) Then $ToolTitle = "File successfully replaced." $ToolTxt = "Done" Else $ToolTitle = "File could *NOT* be replaced." $ToolTxt = "Possibly another open file handle spawned while this script was running." & @CRLF & _ "Simply start over again, please." MsgBox(48, $ToolTitle, $ToolTxt) EndIf EndIf EndFunc ;==>ReplaceFile  
    • By XinYoung
      Greetings!
      I am in need of your guidance once again. I searched the forums for clicking in span, clicking by class, clicking without an ID or Name, etc., but I am unable to find a solution for my problem.
      I am trying to expand this tree in IE. There is an arrow ( > ) that i need to click, but I can't find a way to do it . Alternatively, I can double-click the text "Servers", but that seems to be even more troublesome. I will have to do this 2-3 more times as the tree expands.
      There appears to be an ID for the tree, simply called "tree", but that isn't working when I send a click to it.

      ;Open an IE session and navigate to pgAdmin. Global $oIE = _IECreate($pgAdmin) ;Maximize the IE window. WinSetState(_IEPropertyGet($oIE, "hwnd"), "", @SW_MAXIMIZE) Sleep(2000) ;Expand the tree $oTree = _IEGetObjById($oIE, "tree") _IEAction($oTree, "click") Any ideas?  
    • By Pricehacker
      Hello again!
      I have tried searching for quite some time now but couldn´t find a single working way to change the class of your GUI that doesn´t include changing it manually after its compilation.
      First or "AutoIt v3 GUI" is a pretty boring name tbh and i would like to spice it up a bit, also, and more importantly, I would like to identify my windows by something other than its title as it will change depending on some factors and im using two different programs independently as multi threading isn't supported.
      Any help is appreciated! Thank you!
×
×
  • Create New...