AlexII Posted February 23, 2009 Share Posted February 23, 2009 I try to use the method .WinList () of AutoItX component in VBScript (I need to follow state of the windows). Repeated calls of this method causes an increase memory size occupied by this script more and more.Steps to reproduce this behaviorTrying simple script:Option Explicit Dim objAutoItX Dim arrWinList Set objAutoItX = WScript.CreateObject("AutoItX3.Control") Do arrWinList = objAutoItX.WinList("[ALL]") WScript.Sleep 200 Loop Set objAutoItX = Nothing WScript.Quit 0The memory occupied by this script will continuously grow.Any comments, please?!OFF: Sorry, I'm not speaking English. Link to comment Share on other sites More sharing options...
StSchnell Posted February 23, 2009 Share Posted February 23, 2009 (edited) Hello AlexII, I do not check your code, but I mean you forgot the condition and your loop works for ever: Do While|Until Condition ... Loop or Do ... Loop While|Until Condition Look at the example in the help file. Cheers Stefan P.S. Is not necessary to say sorry for your english knowledge, it is good. Edited February 23, 2009 by StSchnell Meet me at XING Visit my private homepage Visit my commercial homepage Look at my book inter alia about AutoIt and SAP Link to comment Share on other sites More sharing options...
Richard Robertson Posted February 23, 2009 Share Posted February 23, 2009 Not only does your post have nothing to do with his problem, it is also wrong. VB does not require conditions on loops. The reason the memory grows is that the object must return an array but the host is not freeing the array. Link to comment Share on other sites More sharing options...
AlexII Posted February 24, 2009 Author Share Posted February 24, 2009 I do not check your code, but I mean you forgot the condition and your loop works for ever.Yes, I know about it. This was only a demonstration example to reproduce incorrectly behavior. For example, full script listing: expandcollapse popupOption Explicit Dim objAutoItX Dim objSWbemServicesEx Dim dictOldWinList Dim dictNewWinList Dim arrWinList Dim arrOldWinListHandles Dim i Dim strItHandle Set objAutoItX = WScript.CreateObject("AutoItX3.Control") Set dictOldWinList = WScript.CreateObject("Scripting.Dictionary") Set objSWbemServicesEx = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") objAutoItX.AutoItSetOption "WinWaitDelay", 100 ' Search only top-level windows objAutoItX.AutoItSetOption "WinSearchChildren", 0 ' Search top-level and child windows 'objAutoItX.AutoItSetOption "WinSearchChildren", 1 arrWinList = objAutoItX.WinList("[ALL]") For i = 1 to arrWinList(0, 0) dictOldWinList.Add arrWinList(1, i), arrWinList(0, i) Next Do Set dictNewWinList = WScript.CreateObject("Scripting.Dictionary") arrWinList = objAutoItX.WinList("[ALL]") For i = 1 to arrWinList(0, 0) If Not dictOldWinList.Exists(arrWinList(1, i)) Then strItHandle = "[HANDLE:" & arrWinList(1, i) & "]" WScript.Echo Time() & " | New window created." & vbCrLf & _ vbTab & "Handle: [" & arrWinList(1, i) & "]" & vbCrLf & _ vbTab & "Title: [" & arrWinList(0, i) & "]" & vbCrLf & _ vbTab & "Process ID: [" & objAutoItX.WinGetProcess(strItHandle) & "]" & vbCrLf & _ vbTab & "Process: [" & GetProcessNameByPID(objAutoItX.WinGetProcess(strItHandle)) & "]" & vbCrLf & _ vbTab & "Position: [" & objAutoItX.WinGetPosX(strItHandle) & "x" & objAutoItX.WinGetPosY(strItHandle) & "]" & vbCrLf & _ vbTab & "Size: [" & objAutoItX.WinGetPosWidth(strItHandle) & "x" & objAutoItX.WinGetPosHeight(strItHandle) & "]" & vbCrLf End If dictNewWinList.Add arrWinList(1, i), arrWinList(0, i) Next arrOldWinListHandles = dictOldWinList.Keys For i = 0 To dictOldWinList.Count - 1 If Not dictNewWinList.Exists(arrOldWinListHandles(i)) Then WScript.Echo Time() & " | Window destroyed." & vbCrLf & _ vbTab & "Handle: [" & arrOldWinListHandles(i) & "]" & vbCrLf & _ vbTab & "Title: [" & dictOldWinList.Item(arrOldWinListHandles(i)) & "]" & vbCrLf End If Next dictOldWinList.RemoveAll Set dictOldWinList = Nothing Set dictOldWinList = dictNewWinList Set dictNewWinList = Nothing WScript.Sleep 200 Loop WScript.Quit 0 '============================================================================= '============================================================================= Function GetProcessNameByPID(PID) GetProcessNameByPID = "unknown" ' If process already non-exists On Error Resume Next GetProcessNameByPID = objSWbemServicesEx.Get("Win32_Process.Handle='" & PID & "'").Name End Function '============================================================================= Link to comment Share on other sites More sharing options...
AlexII Posted February 24, 2009 Author Share Posted February 24, 2009 The reason the memory grows is that the object must return an array but the host is not freeing the array.There are any ways to solve this problem? I also tryed Erase arrWinList with badly result. Richard, sorry, I have a question: «but the host is not freeing», in this case, you mean that the «host» Windows Script Host or AutoItX? I try calling method .WinList() in AutoIt script also (for debugging only, I remember about «WinList» function ): Local $arrWinList Local $objAutoItX = ObjCreate("AutoItX3.Control") Do $arrWinList = $objAutoItX.WinList("[ALL]") Sleep(200) $arrWinList = 0 Until False $objAutoItX = 0 Exit(0) with identifically results memory grows by this script too. Link to comment Share on other sites More sharing options...
Richard Robertson Posted February 24, 2009 Share Posted February 24, 2009 The "host" is the Windows script host. AutoItX is creating an array. This array is being passed to the WSH, and the memory isn't being freed at any point. I really don't know anything about VB script but I do know that unfreed arrays will pile up. Link to comment Share on other sites More sharing options...
wraithdu Posted February 25, 2009 Share Posted February 25, 2009 (edited) This is an interesting problem. Alex's last example does consume memory, even though he is freeing the array. It seems to be a memory leak in the COM object. Even this will consume memory - Local $arrWinList Local $objAutoItX = ObjCreate("AutoItX3.Control") Do $objAutoItX.WinList("[ALL]") Sleep(200) Until False $objAutoItX = 0 Exit(0) However replacing the COM object with a normal WinList() will not consume memory. Edited February 25, 2009 by wraithdu Link to comment Share on other sites More sharing options...
AlexII Posted February 25, 2009 Author Share Posted February 25, 2009 The "host" is the Windows script host. AutoItX is creating an array. This array is being passed to the WSH, and the memory isn't being freed at any point. I really don't know anything about VB script but I do know that unfreed arrays will pile up. This is an interesting problem. Alex's last example does consume memory, even though he is freeing the array. It seems to be a memory leak in the COM object. Even this will consume memory However replacing the COM object with a normal WinList() will not consume memory.Richard, wraithdu, thanks. I understand that too. However, such behavior is observed in various scripting languages using .WinList() by AutoItX (COM), and this alerted me. Do you think, can does something in AutoItX? Maybe try to make a ticket in bug-tracker about this behavior? Link to comment Share on other sites More sharing options...
Richard Robertson Posted February 25, 2009 Share Posted February 25, 2009 The problem comes in that the COM object has to return an array. There's no easy way to always enforce the freeing of such an array. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now