cappy2112

Difficulty copying 2DArray, returned from WinList()

6 posts in this topic

#1 ·  Posted (edited)

Hi,

 

It's been a while since I've used AutoIt, but I'm having fun with it again.

I'm running on Windows 7 Pro, 64_bit. with AutoIt 3.3.14.2+ 

 

In my program, I've called Winlist(), so that I can get a list of all windows on the system.

I then iterate through the titles, and attempt to copy the title & handle of Windows I'm specifically interested in.

While this seems to be a very easy task, I'm having a strange problem copying the title & handle of the two windows that I'm interested in.

In the For loop:

For $i = 1 To $AllWindowsCount

ConsoleWrite() displays the expected Title & handle, from the WindowsDupe array, so it appears that the copy from the $AllWindows array

works as expected.

However, when

_ArrayDisplay($WindowsDupe)

is called after the for loop, $WindowsDupe is empty.

 

I wasn't able to find any functions in the help file, for copying entire arrays or certain elements, so I thought I would just copy them manually, as seen in the for loop.

What am I doing wrong with the WindowsDupe array?

 

Thanks

 

Thanks

 

My code is attached.

ListWindows2.au3

Edited by cappy2112
Added AutoIt version number, for clarity

Share this post


Link to post
Share on other sites



#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Run_Tidy=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <MsgBoxConstants.au3>
#include <AutoItConstants.au3>
#include <Array.au3>

_Main()

; ******************************
; GLOBAL SETTINGS
;
AutoItSetOption("WinTitleMatchMode", 2) ; match ANY substring in the title
Break($BREAK_ENABLE)
;
; ******************************


Func FindAllWindows($titlematch)

    Local $NonHIWindowCount = 0
    Local $AllWindowsCount = 0
    Local $AllWindows
    Local $i
    Local $WindowsDupe[10][2] ; arbitrary size, will ReDim later
    Local $TitleMatchCount = 0
    Local $temp

    $AllWindows = WinList()


    $AllWindowsCount = $AllWindows[0][0]
    MsgBox($MB_OK, "WINDOW COUNT", "There are " & $AllWindowsCount & " Windows")

    ReDim $WindowsDupe[(UBound($AllWindows)) - 1][2]
    ;_ArrayColInsert($WindowsDupe, 1) ; add the second dimension
    ;$count = 0
    $TitleMatchCount = 0
    For $i = 0 To $AllWindowsCount

        If StringInStr($AllWindows[$i][0], $titlematch) Then

            $WindowsDupe[$TitleMatchCount][0] = $AllWindows[$i][0] ; copy this HI window's title
            $WindowsDupe[$TitleMatchCount][1] = $AllWindows[$i][1] ; copy this HI window's handle

            ConsoleWrite("Idx = " & $i & "  Title: " & $WindowsDupe[$i][0] & "Hndl: " & $WindowsDupe[$i][1] & @CRLF)
            $TitleMatchCount += 1

        EndIf
    Next
    ReDim $WindowsDupe[$TitleMatchCount][2]
    ;$WindowsDupe[0][0] = $TitleMatchCount
    ;_ArrayDisplay($WindowsDupe, $TitleMatchCount + 1)

    Return $WindowsDupe ; return a list of all windows

EndFunc   ;==>FindAllWindows


Func _Main()


    Local $wHnd
    Local $hiWindowList
    Local $WindowCount
    Local $WindowList

    $WindowList = FindAllWindows("Untitled - Notepad")
    _ArrayDisplay($WindowList)

    MsgBox($MB_OK, "AFTER RETURN", "RETURNED FROM FINDALLWINDOWS()")


EndFunc   ;==>_Main

 


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

Monkey's are, like, natures humans.

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

cappy2112,

The information is there, but because you make the Dupe array as big as the WinList return, the found data is hidden somewhere within it. Best to do something like this:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
    #AutoIt3Wrapper_Run_Tidy=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <MsgBoxConstants.au3>
#include <AutoItConstants.au3>
#include <Array.au3>

_Main()

; ******************************
; GLOBAL SETTINGS
;
AutoItSetOption("WinTitleMatchMode", 2) ; match ANY substring in the title
Break($BREAK_ENABLE)
;
; ******************************


Func FindAllWindows($titlematch)

    Local $NonHIWindowCount = 0
    Local $AllWindowsCount = 0
    Local $AllWindows
    Local $i
    Local $WindowsDupe[1][2] = [[0]]
    Local $TitleMatchCount = 0
    Local $temp

    $AllWindows = WinList()

    _ArrayDisplay(WinList)

    $AllWindowsCount = $AllWindows[0][0]
    MsgBox($MB_OK, "WINDOW COUNT", "There are " & $AllWindowsCount & " Windows")

    $TitleMatchCount = 0
    For $i = 1 To $AllWindowsCount

        If StringInStr($AllWindows[$i][0], $titlematch) <> 0 Then
            $TitleMatchCount += 1
            ReDim $WindowsDupe[$TitleMatchCount + 1][2]
            $WindowsDupe[$TitleMatchCount][0] = $AllWindows[$i][0] ; copy this HI window's title
            $WindowsDupe[$TitleMatchCount][1] = $AllWindows[$i][1] ; copy this HI window's handle
        EndIf
    Next

    ;$WindowsDupe[0][0] = $TitleMatchCount
    _ArrayDisplay($WindowsDupe, "Dupe array", Default, 8)

    Return $WindowsDupe ; return a list of all windows

EndFunc   ;==>FindAllWindows


Func _Main()


    Local $wHnd
    Local $hiWindowList
    Local $WindowCount
    Local $WindowList

    $WindowList = FindAllWindows("Untitled - Notepad")
    _ArrayDisplay($WindowList, "Returned", Default, 8)

    MsgBox($MB_OK, "AFTER RETURN", "RETURNED FROM FINDALLWINDOWS()")


EndFunc   ;==>_Main

Now the Dupe array is only as large as it needs to be.

M23

Edit: I see JohnOne had the same idea.

Edited by Melba23

Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

Share this post


Link to post
Share on other sites
11 minutes ago, JohnOne said:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Run_Tidy=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <MsgBoxConstants.au3>
#include <AutoItConstants.au3>
#include <Array.au3>

_Main()

; ******************************
; GLOBAL SETTINGS
;
AutoItSetOption("WinTitleMatchMode", 2) ; match ANY substring in the title
Break($BREAK_ENABLE)
;
; ******************************


Func FindAllWindows($titlematch)

    Local $NonHIWindowCount = 0
    Local $AllWindowsCount = 0
    Local $AllWindows
    Local $i
    Local $WindowsDupe[10][2] ; arbitrary size, will ReDim later
    Local $TitleMatchCount = 0
    Local $temp

    $AllWindows = WinList()


    $AllWindowsCount = $AllWindows[0][0]
    MsgBox($MB_OK, "WINDOW COUNT", "There are " & $AllWindowsCount & " Windows")

    ReDim $WindowsDupe[(UBound($AllWindows)) - 1][2]
    ;_ArrayColInsert($WindowsDupe, 1) ; add the second dimension
    ;$count = 0
    $TitleMatchCount = 0
    For $i = 0 To $AllWindowsCount

        If StringInStr($AllWindows[$i][0], $titlematch) Then

            $WindowsDupe[$TitleMatchCount][0] = $AllWindows[$i][0] ; copy this HI window's title
            $WindowsDupe[$TitleMatchCount][1] = $AllWindows[$i][1] ; copy this HI window's handle

            ConsoleWrite("Idx = " & $i & "  Title: " & $WindowsDupe[$i][0] & "Hndl: " & $WindowsDupe[$i][1] & @CRLF)
            $TitleMatchCount += 1

        EndIf
    Next
    ReDim $WindowsDupe[$TitleMatchCount][2]
    ;$WindowsDupe[0][0] = $TitleMatchCount
    ;_ArrayDisplay($WindowsDupe, $TitleMatchCount + 1)

    Return $WindowsDupe ; return a list of all windows

EndFunc   ;==>FindAllWindows


Func _Main()


    Local $wHnd
    Local $hiWindowList
    Local $WindowCount
    Local $WindowList

    $WindowList = FindAllWindows("Untitled - Notepad")
    _ArrayDisplay($WindowList)

    MsgBox($MB_OK, "AFTER RETURN", "RETURNED FROM FINDALLWINDOWS()")


EndFunc   ;==>_Main

 

 

ReDim $WindowsDupe[(UBound($AllWindows))  -1][2]

Why? All of the examples I've seen- including in the help file,
always show UBound(Array) +1.

Isn't dimension [2] out of bounds, for a 2D array??

 
 ReDim $WindowsDupe[$TitleMatchCount + 1][2]
 Please explain dimension [2], since this is a 2D array. Do array indices start at 0 or 1, in AutoIT?


     
     

 

 

Share this post


Link to post
Share on other sites

Thank you. The cobwebs are slowly melting ;-)

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

  • Similar Content

    • JohnNash
      WinList fails now and then, why?
      By JohnNash
      So the code I use is as follows:
      Local $InstancesList = WinList("[REGEXPTITLE:(?i)(.*Paint.*|.*WinAmp.*)]")
      And then if this number changes, I do something. But once in a while I SEE a new window paint being opened but nothing happens. 
      So I added logs and printed the InstancesList and saw it did not pick up the new paint. 
      Now I also added a WinList with Class to doublecheck, but still now and then it fails. So I was wondering if this is a known problem, and whether there are alternatives of workarounds.
       
    • JohnNash
      Once in a hundred runs winlist does not pick up a window it should
      By JohnNash
      Hi, I use winlist to count the amount of instances of a specific window (in combination with a reg expression). Over multiple runs, it seems that it fails 1 in a hundred times more or less.                                   Any idea how/why? And are there alternatives to use as a backup/check?
       
                                                                                                                                                                                                                                                                                                                                                                      
       
    • GarnetDagger
      How to check if $array is Single or 2d/Multi-Array
      By GarnetDagger
      I get a database result back as sometimes as single array and sometimes multi array (I understand that is bad practice in general and I am trying to fix that, because there are some errors in my database)
       
      but how can I error handle the best way or determine when something is single or multi array without making my script to break?
       
      I am very poor at @error handling in such cases
       
      for example $ncatid = $array[7]
      (because it is the answer i got back from database is multi array, that is because the item is unfortunate stored double which i am trying to fix in proper manner)
      I get the error of, Array variable has incorrect number of subscripts or subscript dimension range exceeded
       
       
       
       
    • marc0v
      AutoItX, WinList function memory leak
      By marc0v
      All my tests done on WinXP SP3, AutoItX v3.3.0.0
      My AutoItX is not up-to-date, however the changelog does not record any change regarding this problem.

      The issue is known :

      * each call to o_AutoItX3Obj.WinList can consumme up to 4ko (in my tests),
      which are not released even when exiting a sub or setting the o_AutoItX3Obj object to Nothing
      -> this is a problem, for example, for ever-runnning scripts that do repetitive call to WinList
      * a work-around : enumerate windows instead of using WinList
      VBS Code

      Option Explicit MAIN() Sub MAIN() Dim s_win_id, arr Dim o_AutoItX3Obj Set o_AutoItX3Obj = CreateObject("AutoItX3.Control") ' s_win_id : the advanced filter parameter that would have been used in the WinList function ' s_win_id : must not contain the INSTANCE parameter (it seems it just would be ignored) ' WinTitleMatchMode : the title match mode that would have been used with the WinList function ' WinSearchChildren : the child windows mode that would have been used with the WinList function ' *** EXAMPLE 1 *** ' s_win_id = "TITLE:a", with WinTitleMatchMode substring (=2), No WinSearchChildren (=0) ' there should be some of theses s_win_id = "TITLE:a" o_AutoItX3Obj.AutoItSetOption "WinTitleMatchMode", 2 o_AutoItX3Obj.AutoItSetOption "WinSearchChildren", 0 ' call the pseudo WinList function (ENUM_WIN) arr = ENUM_WIN(o_AutoItX3Obj, s_win_id) ' look for results SHOW_RESULTS o_AutoItX3Obj, s_win_id, arr ' *** EXAMPLE 2 *** ' s_win_id = "TITLE:a; REGEXPCLASS:a", with WinTitleMatchMode substring (=2), No WinSearchChildren (=0) ' there should be at least the 'Program Manager' [Class:Progman], which is the Windows desktop s_win_id = "TITLE:a; REGEXPCLASS:a" o_AutoItX3Obj.AutoItSetOption "WinTitleMatchMode", 2 o_AutoItX3Obj.AutoItSetOption "WinSearchChildren", 0 ' call the pseudo WinList function (ENUM_WIN) arr = ENUM_WIN(o_AutoItX3Obj, s_win_id) ' look for results SHOW_RESULTS o_AutoItX3Obj, s_win_id, arr End Sub Sub SHOW_RESULTS(ByVal o_AutoItX3Obj, ByVal s_win_id, ByVal arr) Dim s_res, i s_res = "Number of windows matching [" & s_win_id & "] : " & arr(0, 0) & vbCr s_res = s_res & "WinTitleMatchMode : " & o_AutoItX3Obj.AutoItSetOption("WinTitleMatchMode", 0) & ", " s_res = s_res & "WinSearchChildren : " & o_AutoItX3Obj.AutoItSetOption("WinSearchChildren", 0) & vbCr s_res = s_res & "(message boxes can cut long text)" & vbCr & vbCr s_res = s_res & "Num Handle" & vbTab & "Title" & vbCr & vbCr For i = 1 To UBound(arr, 2) s_res = s_res & i & ". " & arr(1, i) & vbTab & "[" & arr(0, i) & "]" & vbCr Next MsgBox s_res, vbInformation, WScript.ScriptName End Sub ' Re-usable code begins here (could be optimized if hundreds of matching windows are expected) ' ENUM_WIN returns an 2-Dim array, same formatting as by WinList function Function ENUM_WIN(ByVal o_AutoItX3Obj, ByVal s_win_id) Dim s_win_handle, s_win_title, arr, i ReDim arr(1, 0) arr(0, 0) = 0 ' will hold the number of found windows, like the WinList function arr(1, 0) = 0 ' will not be used i = 1 ' because Instances are 1-based Do s_win_handle = o_AutoItX3Obj.WinGetHandle("[" & s_win_id & "; INSTANCE:" & i & "]") If s_win_handle = "" Then Exit Do ' enumeration finished s_win_title = o_AutoItX3Obj.WinGetTitle("[HANDLE:" & s_win_handle & "]") ReDim Preserve arr(1, i) arr(0, i) = s_win_title ' title can be an empty string arr(1, i) = s_win_handle ' handle should always be a valid hex string number (32/64 bits ?) i = i + 1 Loop arr(0, 0) = i - 1 ' record the number of found windows ENUM_WIN = arr End Function
      * note 1 :
      enumerating windows could have timing issues if some windows matching the criteria
      are appearing/disappearing while doing the enumeration... (I didn't test that)
      * note 2 :
      if it impossible to avoid memory leak in COM components returning arrays,
      then WinList could return a simple string with titles/handles separated by Chr(0),
      (assuming there are no Chr(0) inside window titles ?)
      then the user would use the Split function to get an 1-Dim array : [title1, handle1, title2, handle2, title3, handle3] etc...
      This string-type return could be an optional parameter given to the WinList function :
      arr = o_AutoItX3Obj.Winlist("title" [, "text" [, return type]])
    • Ascend4nt
      _WinGetAltTabWinList
      By Ascend4nt
      _WinGetAltTabWinList

      Since Authenticity was awesome enough to post how to get the Alt-Tab-able Windows, I decided to wrap it into a simple UDF that can be used just as WinList. The potential use is great. One person has already used the code to create a replacement Alt-Tab interface.

      Simple example:

      #include "_WinGetAltTabWinList.au3" #include <Array.au3> Local $aWindows=_WinGetAltTabWinList("","",True) _ArrayDisplay($aWindows)
      *UPDATES:11/30/2010:
      Fixed extended-style check to skip over certain windows that shouldn't be in the list, cleaned up and shortened code a bit. Download the ZIP at my Site
      Ascend4nt's AutoIT Code License agreement:
      While I provide this source code freely, if you do use the code in your projects, all I ask is that:
      If you provide source, keep the header as I have put it, OR, if you expand it, then at least acknowledge me as the original author, and any other authors I credit If the program is released, acknowledge me in your credits (it doesn't have to state which functions came from me, though again if the source is provided - see #1) The source on it's own (as opposed to part of a project) can not be posted unless a link to the page(s) where the code were retrieved from is provided and a message stating that the latest updates will be available on the page(s) linked to. Pieces of the code can however be discussed on the threads where Ascend4nt has posted the code without worrying about further linking.