I'm trying to fill a ListView with all normal viewable windows to act with them.
First I tried with WinList:
Local $aWinList = WinList("[REGEXPTITLE:(?i)(.+)]") Local $aTmp, $iID ;~ _ArrayDisplay($aWinList) For $i = $aWinList To 1 Step -1 ; going backwards not disturbing the index while cycling through and deleting some If StringStripWS( $aWinList[$i], 3) == "" Or _ Not BitAND(WinGetState($aWinList[$i]), $WIN_STATE_VISIBLE) Or _ BitAND(WinGetState($aWinList[$i]), $WIN_STATE_MINIMIZED ) Then _ArrayDelete($aWinList, $i) Else ; Window has a Title and is "visible" $aTmp = WinGetPos($aWinList[$i]) If $aTmp < -1000 Or $aTmp < -1000 Then ; Window is minimized or tray icon _ArrayDelete($aWinList, $i) EndIf EndIf Next $aWinList = UBound($aWinList)-1 ; getting actual # of windows ; Each row is now [ID]=> [Title], [hWnd] But it keeps getting Windows which are definitely not there at least not visible:
Those windows "Rechner", "Einstellungen", "Netflix", "Microsoft Store", ... are not there!?!
It should list only the first three windows, which are real.
I even tried it with _WinAPI_ UDF:
$hWnd = _WinAPI_GetForegroundWindow() ; Add items _GUICtrlListView_BeginUpdate($idListview) If $hWnd <> 0 Then $iI = 0 Do If _WinAPI_IsWindow($hWnd) And _WinAPI_IsWindowVisible Then _GUICtrlListView_AddItem($idListview, WinGetTitle($hWnd)) _GUICtrlListView_AddSubItem($idListview, $iI, $hWnd, 1) $iI += 1 $hWnd = _WinAPI_GetWindow($hWnd, $GW_HWNDNEXT) EndIf Until $hWnd = 0 EndIf But it is the same...
How can i distinguish those invisible windows from normal ones?
PS: I'm using Windows 10, maybe it is important to know?
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 126.96.36.199+
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.
_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?
My code is attached.
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.
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?
All my tests done on WinXP SP3, AutoItX v188.8.131.52
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
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]])