Leaderboard
Popular Content
Showing content with the highest reputation on 11/06/2024 in all areas
-
At first glance, you do not use _GDIPlus_GraphicsDispose2 points
-
Update the script above to Version: 4.0 I lightened it up a bit from the legacies it had from the previous script (with big numbers) which assumed that each Vpoint could be made up of more pixels so that it is more readable and lighter2 points
-
Something looks wrong in the _ScreenCapture. You are reusing the same variable for 2 different purposes (without cleaning up the memory) : Here : $hBitmap = _WinAPI_AdjustBitmap($hHBitmap, $iBmpW, $iBmpH, $HALFTONE, $tAdj) and there : $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap) That must create major memory leak, IMO.1 point
-
StringSplit Example
mr-es335 reacted to pixelsearch for a topic
@mr-es335 i don't know about other users but when I started to learn AutoIt and a new function (like StringSplit) was needed in a script I was writing, then I put the script "on hold" and do many "little tests" I could with this new function (StringSplit), trying to understand exactly how it works, even if it will take me hours ! Gladly the help file is a big help and after these tests were done, only then I went back to the script to continue it. Now you know that your issue concerns the array $_aGetType[] and this array was returned by... StringSplit, then you should take a little time to do some external little tests to understand SpringSplit a bit more, for example : #include <Array.au3> _Split("F:") _Split("F:\") _Split("F:\Audio") _Split("F:\Audio\Type_1") _Split("F:\Audio\Type_1\TestMe") _Split("F:\Audio\Type_1\TestMe\") Func _Split($sString) Local $aArray = StringSplit($sString, "\") If @error Then ConsoleWrite($sString & " error = " & @error & " (no delimiter found)" & @crlf) _ArrayDisplay($aArray, $sString) EndFunc Now you should focus on the value of the 1st element of the array, i.e. $aArray[0] which always exists in this example because we didn't use the flag $STR_NOCOUNT . As you can see, its value goes from 1 to 5 in this example, and the help file is clear about that : StringSplit returns an array, by default the first element ($aArray[0]) contains the number of strings returned, the remaining elements ($aArray[1], $aArray[2], etc.) contain the delimited strings. So by testing the value of $aArray[0] you should achieve your goal (i.e. if the value is < 3 then you can be sure that the user didn't select the 'Type_1' subfolder, because when 'Type_1' is found in the selected path, then $aArray[0] >= 3 3 if "F:\Audio\Type_1" 4 if "F:\Audio\Type_1\TestMe" 5 if "F:\Audio\Type_1\TestMe\" etc... Hope it helps1 point -
Unable to identify the objects in Data window using Autoscript
argumentum reacted to Harshu for a topic
We would need AutoIt for automating our Test cases for Regression or System Testing. To our knowledge, powerbuilder does not offer any testing tool. Will get in touch with the Appeon team and get their inputs on the usage of custom controls and UIAutomation for those. Thanks for the suggestions.1 point -
OCR from a small area
ioa747 reacted to argumentum for a topic
https://www.autoitscript.com/forum/index.php?showtopic=197259&view=findpost&p=1414754 ?1 point -
How much are you willing to pay ? You should know that we are here to help ppl having issues with their scripts. We are not here to receive order to write stuff for you.1 point
-
1 point
-
OCR from a small area
ioa747 reacted to argumentum for a topic
Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sFileName) If @error Then Return SetError(1, 0, "") ; because the user ( me ) might do the unexpected ;)1 point -
this is for small numbers like I simplified the process as much as possible by removing the unnecessary stuff like the area selector. ; https://www.autoitscript.com/forum/topic/211521-ocr-from-a-small-area/?do=findComment&comment=1538057 ; Version: 4.0 #include <GDIPlus.au3> #include <Array.au3> #include <File.au3> Local $Result = _GetNumber(@ScriptDir & "\100num\152.png") MsgBox($MB_SYSTEMMODAL, "_GetNumber", $Result) ;~ Test(@ScriptDir & "\100num") ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetNumber($sFileName, $hColor = 0x00FF00) ; Main Program ; Capture the color map for the specified area Local $aColorMap = CaptureAreaColorMap($sFileName) ;~ _ArrayDisplay($aColorMap) Local $Result = FindNumberUsingColorMap($aColorMap, $hColor) ;~ MsgBox($MB_SYSTEMMODAL, "$Result", $Result) Return $Result EndFunc ;==>_GetNumber ;-------------------------------------------------------------------------------------------------------------------------------- Func CaptureAreaColorMap($sFileName) ; create color map array ; Initialize GDI+ to work with bitmaps _GDIPlus_Startup() ; Capture the screen area as a bitmap Local $hBitmap = _GDIPlus_BitmapCreateFromFile($sFileName) ; Get the width and height of the captured area Local $width = _GDIPlus_ImageGetWidth($hBitmap) Local $height = _GDIPlus_ImageGetHeight($hBitmap) ;~ ConsoleWrite("Image: $width=" & $width & ", $height=" & $height & @CRLF) ; Create an array to store color values Local $aColorMap[$width][$height] ; Loop through each pixel in the bitmap and retrieve its color For $y = 0 To $height - 1 For $x = 0 To $width - 1 ; Get the pixel color from the bitmap in ARGB format Local $argbColor = _GDIPlus_BitmapGetPixel($hBitmap, $x, $y) ; Convert ARGB to BGR for comparison (ignore the alpha channel) Local $bgrColor = BitAND($argbColor, 0x00FFFFFF) $aColorMap[$x][$y] = $bgrColor Next Next ; Cleanup resources _GDIPlus_BitmapDispose($hBitmap) _GDIPlus_Shutdown() Return $aColorMap EndFunc ;==>CaptureAreaColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func FindNumberUsingColorMap($aColorMap, $hColor = 0x00FF00) ; find number in color map array Local $width = UBound($aColorMap, 1) Local $height = UBound($aColorMap, 2) Local $firstRow = -1, $lastRow = -1, $firstCol = -1, $lastCol = -1 ; Scan for the first and last rows and columns with $hColor pixels For $y = 0 To $height - 1 For $x = 0 To $width - 1 If $aColorMap[$x][$y] = $hColor Then If $firstRow = -1 Then $firstRow = $y $lastRow = $y If $firstCol = -1 Or $x < $firstCol Then $firstCol = $x If $lastCol = -1 Or $x > $lastCol Then $lastCol = $x EndIf Next Next If $firstRow = -1 Or $lastRow = -1 Or $firstCol = -1 Or $lastCol = -1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No color found" & @TAB & @TAB) Exit EndIf ; each number Display is a matrix of 14x20 pixels Local $numberWidth = 14 ; set number width per digit Local $numberSpace = 2 ; set Space between digits Local $Empty = 0, $Corection = 0 ; Corection for boundaries if 1st digit = 1 For $x = $firstCol To $lastCol - 1 If $aColorMap[$x][$firstRow] = 0x000000 Then $Empty += 1 If $Empty = 3 Then ;found 1st Space between digits $Corection = $firstCol - 1 - Abs($x - $numberWidth - $numberSpace) ExitLoop EndIf Else $Empty = 0 EndIf Next If $Corection > 0 Then $firstCol = $firstCol - $Corection Local $numberStart = $firstCol ;~ ConsoleWrite("$Corection=" & $Corection & @CRLF) ;~ ConsoleWrite("Display_boundaries firstRow:" & $firstRow & " lastRow:" & $lastRow & " firstCol:" & $firstCol & " lastCol:" & $lastCol & @CRLF) ;~ ConsoleWrite("" & @CRLF) Local $aNum[11][3] ; Define boundaries for each number position For $i = 1 To 10 $aNum[$i][0] = $numberStart $aNum[$i][1] = $numberStart + $numberWidth If $numberStart + $numberWidth + $numberSpace > $lastCol Then ExitLoop $numberStart += $numberWidth + $numberSpace $aNum[0][0] = $i + 1 Next Local $sNumber ; Generate patterns for each found number For $i = 1 To $aNum[0][0] Local $sPattern = "" For $y = $firstRow To $lastRow For $x = $aNum[$i][0] To $aNum[$i][1] - 1 If $aColorMap[$x][$y] = $hColor Then $sPattern &= "1" Else $sPattern &= "." EndIf Next $sPattern &= @CRLF Next $sNumber &= _GetPattern($sPattern) Next Return $sNumber EndFunc ;==>FindNumberUsingColorMap ;-------------------------------------------------------------------------------------------------------------------------------- Func _GetPattern($sPattern) ; patterns for each digit ;~ ConsoleWrite("**************" & @CRLF & $sPattern & @CRLF) Local $aNumber[10] ; Define simplified patterns for each digit $aNumber[0] = "" ; Pattern for '0' $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= "11.......11.11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= "11....11....11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= "11.11.......11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= "11..........11" & @CRLF $aNumber[0] &= ".............." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[0] &= "...11.11.11..." & @CRLF $aNumber[1] = "" ; Pattern for '1' $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "...11.11......" & @CRLF $aNumber[1] &= "...11.11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= "......11......" & @CRLF $aNumber[1] &= ".............." & @CRLF $aNumber[1] &= "...11.11.11..." & @CRLF $aNumber[1] &= "...11.11.11..." & @CRLF $aNumber[2] = "" ; Pattern for '2' $aNumber[2] &= "...11.11.11..." & @CRLF $aNumber[2] &= "...11.11.11..." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11..........11" & @CRLF $aNumber[2] &= "11..........11" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "............11" & @CRLF $aNumber[2] &= "............11" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "......11.11..." & @CRLF $aNumber[2] &= "......11.11..." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "...11........." & @CRLF $aNumber[2] &= "...11........." & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11............" & @CRLF $aNumber[2] &= "11............" & @CRLF $aNumber[2] &= ".............." & @CRLF $aNumber[2] &= "11.11.11.11.11" & @CRLF $aNumber[2] &= "11.11.11.11.11" & @CRLF $aNumber[3] = "" ; Pattern for '3' $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "......11.11..." & @CRLF $aNumber[3] &= "......11.11..." & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= "............11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= "11..........11" & @CRLF $aNumber[3] &= ".............." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[3] &= "...11.11.11..." & @CRLF $aNumber[4] = "" ; Pattern for '4' $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "......11.11..." & @CRLF $aNumber[4] &= "......11.11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "...11....11..." & @CRLF $aNumber[4] &= "...11....11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "11.......11..." & @CRLF $aNumber[4] &= "11.......11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= "11.11.11.11.11" & @CRLF $aNumber[4] &= "11.11.11.11.11" & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".............." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[4] &= ".........11..." & @CRLF $aNumber[5] = "" ; Pattern for '5' $aNumber[5] &= "11.11.11.11.11" & @CRLF $aNumber[5] &= "11.11.11.11.11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11............" & @CRLF $aNumber[5] &= "11............" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11.11.11.11..." & @CRLF $aNumber[5] &= "11.11.11.11..." & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= "............11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "11..........11" & @CRLF $aNumber[5] &= "11..........11" & @CRLF $aNumber[5] &= ".............." & @CRLF $aNumber[5] &= "...11.11.11..." & @CRLF $aNumber[5] &= "...11.11.11..." & @CRLF $aNumber[6] = "" ; Pattern for '6' $aNumber[6] &= "......11.11..." & @CRLF $aNumber[6] &= "......11.11..." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "...11........." & @CRLF $aNumber[6] &= "...11........." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11............" & @CRLF $aNumber[6] &= "11............" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11.11.11.11..." & @CRLF $aNumber[6] &= "11.11.11.11..." & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= "11..........11" & @CRLF $aNumber[6] &= ".............." & @CRLF $aNumber[6] &= "...11.11.11..." & @CRLF $aNumber[6] &= "...11.11.11..." & @CRLF $aNumber[7] = "" ; Pattern for '7' $aNumber[7] &= "11.11.11.11.11" & @CRLF $aNumber[7] &= "11.11.11.11.11" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "............11" & @CRLF $aNumber[7] &= "............11" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= ".........11..." & @CRLF $aNumber[7] &= ".........11..." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "......11......" & @CRLF $aNumber[7] &= "......11......" & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= ".............." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[7] &= "...11........." & @CRLF $aNumber[8] = "" ; Pattern for '8' $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= "11..........11" & @CRLF $aNumber[8] &= ".............." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[8] &= "...11.11.11..." & @CRLF $aNumber[9] = "" ; Pattern for '9' $aNumber[9] &= "...11.11.11..." & @CRLF $aNumber[9] &= "...11.11.11..." & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= "11..........11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "...11.11.11.11" & @CRLF $aNumber[9] &= "...11.11.11.11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "............11" & @CRLF $aNumber[9] &= "............11" & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= ".........11..." & @CRLF $aNumber[9] &= ".........11..." & @CRLF $aNumber[9] &= ".............." & @CRLF $aNumber[9] &= "...11.11......" & @CRLF $aNumber[9] &= "...11.11......" & @CRLF Switch $sPattern Case $aNumber[0] Return 0 Case $aNumber[1] Return 1 Case $aNumber[2] Return 2 Case $aNumber[3] Return 3 Case $aNumber[4] Return 4 Case $aNumber[5] Return 5 Case $aNumber[6] Return 6 Case $aNumber[7] Return 7 Case $aNumber[8] Return 8 Case $aNumber[9] Return 9 Case Else Return SetError(1, 0, "") EndSwitch EndFunc ;==>_GetPattern ;-------------------------------------------------------------------------------------------------------------------------------- Func Test($sFilePath) ; _GetNumber for all the *.png files in $sFilePath directory ; List all the *.png files in $sFilePath directory Local $aFileList = _FileListToArray($sFilePath, "*.png", $FLTA_FILES) If @error = 1 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "Path was invalid.") Exit EndIf If @error = 4 Then MsgBox($MB_SYSTEMMODAL, "LineNumber:" & @ScriptLineNumber, "No file(s) were found.") Exit EndIf _ArrayColInsert($aFileList, 1) ; add 1 column to hold the numbers For $i = 1 To $aFileList[0][0] $aFileList[$i][1] = _GetNumber($sFilePath & "\" & $aFileList[$i][0]) ; Rename a file using FileMove and overwrite the new file if it exists. ;~ FileMove($sFilePath & "\" & $aFileList[$i][0], $sFilePath & "\" & $aFileList[$i][1] & ".png", $FC_OVERWRITE) Next _ArrayDisplay($aFileList, "$aFileList") EndFunc ;==>Test ;--------------------------------------------------------------------------------------------------------------------------------1 point
-
GDIPlus Dispose/Shutdown review
Hashim reacted to seadoggie01 for a topic
I'm not sure if this is what you mean, but here goes: Create a UDF that is _GDIPlusEx Wrap each GDIPlus function that creates something in a _GDIPlusEx_* function Store each created object in a global array in the UDF _GDIPlusEx_ShutDown walks through each object and destroys it before calling _GDIPlus_ShutDown I did this once, but of course I can't find it now Edit: After re-reading your question, I think I misunderstood, you want to know which functions need to be deleted, don't you? Sorry. Edit 2: I used the help file to determine the destructive counterpart to each function (that you used only, this list isn't complete) _GDIPlus_Startup _GDIPlus_Shutdown _GDIPlus_BitmapCreateFromHBITMAP _GDIPlus_BitmapDispose _GDIPlus_ImageGetDimension _GDIPlus_BitmapCreateFromScan0 _GDIPlus_BitmapDispose _GDIPlus_ImageGetGraphicsContext _GDIPlus_GraphicsDispose _GDIPlus_GraphicsDrawImageRect _GDIPlus_PenCreate _GDIPlus_PenDispose _GDIPlus_GraphicsDrawRect _GDIPlus_BrushCreateSolid _GDIPlus_BrushDispose _GDIPlus_StringFormatCreate _GDIPlus_StringFormatDispose _GDIPlus_FontFamilyCreate _GDIPlus_FontFamilyDispose _GDIPlus_FontCreate _GDIPlus_FontDispose _GDIPlus_RectFCreate _GDIPlus_GraphicsMeasureString _GDIPlus_GraphicsDrawStringEx _GDIPlus_ImageSaveToFile _GDIPlus_ImageDispose _GDIPlus_Shutdown1 point -
Memory leak script stopper ( or not )
ioa747 reacted to argumentum for a topic
I was asking around on how to detect memory leaks and came up with a logger ( or just stop execution, or restart ). Here is the code. ( should have done a UDF but maybe there is no need for such ) #AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 6 -w 7 #include <SQLite.au3> #include <WinAPISys.au3> #include <WinAPIProc.au3> #include <Date.au3> #include <Array.au3>; For _ArrayDisplay() Example() Func Example() ConsoleWrite(MemLeakTooMuch() & @CRLF) ; call once at first to initialize the baseline. Local $a = MemLeakLog(1) ; ..you could call this on the fly and get an array _ArrayDisplay($a) ; call on AdlibRegister() or other means ; Ex: AdlibRegister("OnMemLeakRestart", 3600000) ; once an hour ; While Sleep(50) ; ... ... ; WEnd EndFunc ;==>Example #Region MemLeak Func OnMemLeakRestart() ; Local Static $iTriggered = 0 If MemLeakTooMuch() Then If Not $iTriggered Then $iTriggered = 1 AdlibRegister("OnMemLeakRestart", 60000) ; since it triggered, check more often EndIf If _WinAPI_GetIdleTime() > 600000 Then ; over 10 min. maybe ?, to not bother the user ? ShellExecute(@ScriptFullPath) ; restart itself if it must, but if you do, ; keep that in mind while coding. Exit 3 ; use the exit code you please other than 1 or 2, EndIf ; as AutoIt may use it for itself. EndIf EndFunc ;==>OnMemLeakRestart Func MemLeakLog($ReturnAnArray = 0) Local $aMethod[5] = ["EXITCLOSE_NORMAL", "EXITCLOSE_BYEXIT", "EXITCLOSE_BYCLICK", "EXITCLOSE_BYLOGOFF", "EXITCLOSE_BYSHUTDOWN"] Local $iMethod = Execute("@exitMethod") Local $aDesc[14] = ["number of page faults", "peak working set size, in bytes", "current working set size, in bytes", _ "peak paged pool usage, in bytes", "current paged pool usage, in bytes", "peak nonpaged pool usage, in bytes", _ "current nonpaged pool usage, in bytes", "current space allocated for the pagefile, in bytes", _ "peak space allocated for the pagefile, in bytes", "current amount of memory that cannot be shared with other processes, in bytes", _ "ProcessHandleCount", "ProcessThreadsCount", "GDI objects", "USER objects"] Local $s = @YEAR & "." & @MON & "." & @MDAY & "_" & @HOUR & ":" & @MIN & ":" & @SEC $s &= " - RunTime: " & _Convert(gTimer()) & " - PID: " & @AutoItPID If IsInt($iMethod) Then $s &= " - ExitCode: " & @exitCode $s &= " - ExitMethod: " & $iMethod & " (" & $aMethod[$iMethod] & ")" EndIf Local $a[4][15] $a[1][0] = "Starting:" $a[2][0] = " Exiting:" $a[3][0] = " Diff.:" MemLeakTooMuch() Local $b = MemLeakTooMuch(-2), $c = MemLeakTooMuch(-3) For $n = 0 To UBound($c) - 1 $a[0][$n + 1] = $aDesc[$n] $a[1][$n + 1] = $b[$n] $a[2][$n + 1] = $c[$n] $a[3][$n + 1] = $c[$n] - $b[$n] Switch $n Case 0, 10, 11, 12, 13, 14 ; nothing, is a count number Case Else $a[3][$n + 1] = ByteSuffix($a[3][$n + 1]) EndSwitch $a[3][$n + 1] &= " ( x" & (($b[$n] > 0 And $b[$n] > 0) ? Round($c[$n] / $b[$n], 1) : "1") & " )" Next If Int(Eval("ReturnAnArray")) Then $a[0][0] = _Convert(gTimer()) Return $a Else FileWriteLine(StringTrimRight(@ScriptFullPath, 4) & ".ProcessInfo.log", $s & @CRLF & _ _SQLite_Display2DResult($a, 0, True) & Eval("sErrorHandler") & @CRLF) ; I save the data from ObjEvent("AutoIt.Error", "_ErrFunc") to $sErrorHandler EndIf EndFunc ;==>MemLeakLog Func MemLeakTooMuch($iPid = 0, $iMutliplier = 4) ; in case this is for some other PID, but only one =/ Local Static $aInitProcessMemoryInfo = 99, $aLastProcessMemoryInfo Local $ret = False, $a, $n, $aTemp If $iPid = -2 Then Return $aInitProcessMemoryInfo ; returns the initial readings If $iPid = -3 Then Return $aLastProcessMemoryInfo ; returns the last readings If $aInitProcessMemoryInfo = 99 Then $aTemp = _WinAPI_GetProcessMemoryInfo($iPid) If Not (UBound($aTemp) = 10) Then Return SetError(1, 0, $ret) $aLastProcessMemoryInfo = $aTemp Else $aTemp = _WinAPI_GetProcessMemoryInfo($iPid) If Not (UBound($aTemp) = 10) Then Return SetError(1, 0, $ret) $aLastProcessMemoryInfo = $aTemp For $n = 1 To UBound($aTemp) - 1 ; I don't think "page faults" is leakage, so it's omited. If $aTemp[$n] > $aInitProcessMemoryInfo[$n] * $iMutliplier Then $ret = True Next EndIf ReDim $aLastProcessMemoryInfo[14] ; to hold the next values $aLastProcessMemoryInfo[10] = _WinAPI_GetProcessHandleCount($iPid) If $aLastProcessMemoryInfo[10] > 2000 Then $ret = True ; dropping handles ? $a = _WinAPI_EnumProcessThreads($iPid) $aLastProcessMemoryInfo[11] = UBound($a) - 1 If $aLastProcessMemoryInfo[11] > 200 Then $ret = True ; dropping threads ? If Not $iPid Then $iPid = -1 $aLastProcessMemoryInfo[12] = _WinAPI_GetGuiResources(0, $iPid) ; count of GDI objects. $aLastProcessMemoryInfo[13] = _WinAPI_GetGuiResources(1, $iPid) ; count of USER objects If $aLastProcessMemoryInfo[12] > 1000 Then $ret = True ; dropping GDI objects ? If $aLastProcessMemoryInfo[13] > 2000 Then $ret = True ; dropping USER objects ? If $aInitProcessMemoryInfo = 99 Then gTimer() ; init. the timer now, if was not at the top of the script $aInitProcessMemoryInfo = $aLastProcessMemoryInfo OnAutoItExitRegister("MemLeakLog") ; ..if you wanna keep a log EndIf Return $ret EndFunc ;==>MemLeakTooMuch Func _Convert($ms) ; https://www.autoitscript.com/forum/topic/163621-convert-ms-to-dayhourminsec/?do=findComment&comment=1192334 Local $day, $hour, $min, $sec _TicksToTime($ms, $hour, $min, $sec) If $hour > 24 Then $day = $hour / 24 $hour = Mod($hour, 24) EndIf Return StringReplace(StringFormat("%03i %02i:%02i:%02i", $day, $hour, $min, $sec), "000 ", "") EndFunc ;==>_Convert Func gTimer() Local Static $Timer = TimerInit() Return TimerDiff($Timer) EndFunc ;==>gTimer Func ByteSuffix($iBytes) ; https://www.autoitscript.com/autoit3/docs/functions/FileGetSize.htm Local $iIndex = 0, $aArray = [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB'] While $iBytes > 1023 $iIndex += 1 $iBytes /= 1024 WEnd Return Round($iBytes) & $aArray[$iIndex] EndFunc ;==>ByteSuffix #EndRegion MemLeak I'm gonna use it for a pain in the neck script. If you find ways to improve it, or something I missed, let me know. 2019.01.05 update: Added GDI objects and USER objects. Added return array. Fixed boo-boo. Added Diff. multiplier.1 point