Leaderboard
Popular Content
Showing content with the highest reputation on 11/20/2018 in all areas
-
Note: This is the continuation thread from the original one of 2012. The old one growed over 50 pages...so to make the overview better i created a new main thread for the ISN AutoIt Studio. You can find the old original thread here. The ISN AutoIt Studio is a complete IDE made with AutoIt, for AutoIt! It includes a GUI designer, a code editor (with syntax highlighting, auto complete & intelisense), a file viewer, a backup system and a lot more features!! Here are some screenshots: Here are some higlights: Easy to create/manage/public your AutoIt projects! Integrated GUI-Editor (ISN Form Studio 2) Integrated file & projectmanager Auto backupfunction for your Projects Extendable with plugins! Available in several languages Trophies Syntax highlighting /Autocomplete / Intelisense Macros Changelog manager for your project Detailed overview of the project (total working hours, total size...) Am integrated To-Do List for your project Open Source (You can download the source code from my website) And much much more!!! -> -> Click here to download ISN AutoIt Studio <- <- Here is the link to the german autoit forum where I posted ISN AutoIt Studio the first time: Link For more information visit my Homepage: https://www.isnetwork.at So, have fun with the ISN AutoIt Studio! And feel free to post your feedback, bugreports or ideas for this project here in this thread!1 point
-
If you set the styles of a control with GUICtrlSetStyle() and happen to forget the styles you set, then why not try GUICtrlGetStyle() To get the Hex value e.g. 00100000 then use this little conversion >> Local $aArray = GUICtrlGetStyle($iLabel) _GUICtrlGetStyle_Convert($aArray) _ArrayDisplay($aArray, 'The Style = 0101 & the ExStyle = 00100000'))Function: #include-once #include <WinAPI.au3> ; #FUNCTION# ==================================================================================================================== ; Name ..........: GUICtrlGetStyle ; Description ...: Retrieves the Styles/ExStyles value(s) of a control. ; Syntax ........: GUICtrlGetStyle($hWnd) ; Parameters ....: $hWnd - Control ID/Handle to the control ; Return values .: $aArray[2] = [Style, ExStyle] ; Author ........: guinness ; Example .......: Yes ; =============================================================================================================================== Func GUICtrlGetStyle($hWnd) If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd) EndIf Local $aReturn = [_WinAPI_GetWindowLong($hWnd, $GWL_STYLE), _WinAPI_GetWindowLong($hWnd, $GWL_EXSTYLE)] Return $aReturn EndFunc ;==>GUICtrlGetStyleExample use of Function: #include <Array.au3> ; Required only for _ArrayDisplay(), but not the UDF! #include <GUIConstantsEx.au3> #include 'GUICtrlGetStyle.au3' Example() Func Example() Local $hGUI = GUICreate('GUICtrlGetStyle() Example', 280, 90) ; This label is using 'magic numbers' instead of the constant variables. It's advisable to use $SS_CENTER & $GUI_WS_EX_PARENTDRAG ; instead of 0x0101 & 0x00100000, but this has been done for proof of concept only. See the second _Array display for more details. Local $iLabel = GUICtrlCreateLabel('This is a Label with $SS_CENTER & $GUI_WS_EX_PARENTDRAG set as the Styles.', 10, 10, 270, 45, 0x0101, 0x00100000) ; $SS_CENTER, $GUI_WS_EX_PARENTDRAG Local $iButton = GUICtrlCreateButton('GetStyle Array', 95, 55, 85, 25) GUISetState(@SW_SHOW, $hGUI) Local $aArray = 0 While 1 Switch GUIGetMsg() Case $GUI_EVENT_CLOSE ExitLoop Case $iButton $aArray = GUICtrlGetStyle($iLabel) _ArrayDisplay($aArray) GUICtrlDelete($iLabel) GUICtrlCreateLabel('This is a NEW Label with $SS_CENTER & $GUI_WS_EX_PARENTDRAG set as the Styles/ExStyles.', 10, 10, 270, 50, $aArray[0], $aArray[1]) ; This is the reason why 'magic numbers' were used, so as to see they match the same values in GUICtrlCreateLabel. $aArray = GUICtrlGetStyle($iLabel) _GUICtrlGetStyle_Convert($aArray) _ArrayDisplay($aArray, 'The Style = 0x0101 & the ExStyle = 0x00100000') EndSwitch WEnd GUIDelete($hGUI) EndFunc ;==>Example Func _GUICtrlGetStyle_Convert(ByRef $aArray) If UBound($aArray) = 2 Then $aArray[0] = '0x' & Hex($aArray[0], 4) $aArray[1] = '0x' & Hex($aArray[1], 8) EndIf EndFunc ;==>_GUICtrlGetStyle_Convert1 point
-
Automatically shrink a label to its minimum size
argumentum reacted to boomingranny for a topic
I was working on a project where I have a window without a title, so to move the window I use the window background itself, I have some labels in the window that are right aligned, and they kept getting in the way of the window move.. so I needed a way to shrink the labels to their minimum size, but keep their right alignment. I did have a look through the forum but didn't find anything that would fit my need exactly. To make it as easy as possible I have made the function so it can be called the same way you would set a background color or set a font, you can just call it after label creation: GuiCtrlLabelAutoSize() (see the example below) #include <FontConstants.au3> #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> #include <WinAPIDlg.au3> Local $x = 5, $y = 5 ;create an Example GUI $GUI = GUICreate("Label Example",400,300) GUICtrlCreateLabel("Test label",$x,$y,390,25) GUICtrlSetFont(-1, 9, $FW_NORMAL, $GUI_FONTUNDER, "Aerial") GUICtrlSetBkColor(-1,0xAAAAFF) GUICtrlLabelAutoSize() $y += 30 GUICtrlCreateLabel("Label 2",$x,$y,390,25) GUICtrlSetFont(-1, 10, $FW_BOLD , $GUI_FONTITALIC , "Aerial") GUICtrlSetBkColor(-1,0xAAAAFF) GUICtrlLabelAutoSize(-1,"right") $y += 30 GUICtrlCreateLabel("Label right",$x,$y,390,25) GUICtrlSetFont(-1, 10, $FW_NORMAL, 0, "Aerial") GUICtrlSetBkColor(-1,0xAAAAFF) GUICtrlLabelAutoSize(-1,"right") $y += 30 GUICtrlCreateLabel("Label also right",$x,$y,390,25) GUICtrlSetFont(-1, 10, $FW_NORMAL, 0, "Aerial") GUICtrlSetBkColor(-1,0xAAAAFF) GUICtrlLabelAutoSize(-1,"right") $y += 30 GUICtrlCreateLabel("label centred",$x,$y,390,25) GUICtrlSetFont(-1, 12, $FW_NORMAL, 0, "Times New Roman") GUICtrlSetBkColor(-1,0xAAAAFF) GUICtrlLabelAutoSize(-1,"centre") GUISetState() Do Until GUIGetMsg() = $GUI_EVENT_CLOSE ; #FUNCTION# ==================================================================================================================== ; Name ..........: GUICtrlLabelAutoSize ; Description ...: Shrinks a label to its minimum size, and aligns (left, right, or centre) within its area ; Author(s)......: Daniel Barnes, with help from the AutoIt help file _WinAPI_GetTextExtentPoint32 example! ; Modified.......: 2018/11/20 ; =============================================================================================================================== Func GUICtrlLabelAutoSize($idLbl=-1,$align="left") $sText = GUICtrlRead($idLbl) $hwnd = GUICtrlGetHandle($idLbl) ;get the handle of the label control If $idLbl = -1 Then $idLbl = _WinAPI_GetDlgCtrlID($hwnd) ;get the ID, if we used -1 (last created control) If Not IsHWnd($hwnd) Then ;basic error handling SetError(1) return endif Local $hDC = _WinAPI_GetDC($hWnd) ; Get the device context handle of the current window. Local $hFont = _SendMessage($hWnd, $WM_GETFONT) ; Retrieve the font with which the control is currently drawing its text. Local $hSelectObject = _WinAPI_SelectObject($hDC, $hFont) ; Select the object of the context device. Local $tSIZE = _WinAPI_GetTextExtentPoint32($hDC, $sText) ; Retrieve the height & width of a string. _WinAPI_SelectObject($hDC, $hSelectObject) _WinAPI_ReleaseDC($hWnd, $hDC) ; Release the device context. Local $aReturn[2] = [DllStructGetData($tSIZE, 1), DllStructGetData($tSIZE, 2)] ; Set an array with the width & height of the string. $hParent = _WinAPI_GetParent ( $hwnd) ;Get the handle of the parent window $aPos = ControlGetPos($hParent,"",$idLbl) ;get the position of the label Switch $align Case "left" GUICtrlSetPos($idLbl,$aPos[0],$aPos[1],$aReturn[0],$aReturn[1]) ;resize the label Case "right" $left = $aPos[0]+$aPos[2]-$aReturn[0] GUICtrlSetPos($idLbl,$left,$aPos[1],$aReturn[0],$aReturn[1]) ;resize the label Case "centre" $left = $aPos[0]+(($aPos[2]-$aReturn[0])/2) GUICtrlSetPos($idLbl,$left,$aPos[1],$aReturn[0],$aReturn[1]) ;resize the label EndSwitch EndFunc1 point -
@Acanis It appears that they changed something in the latest version of ChromeDriver. I'll post back if I get it working. Dan P.S. You could also try downgrading to the prior version of ChromeDriver.1 point
-
There is a much easier way to install it. Use the zip version of CCleaner. It is what I use. All you need to do is unzip it and your done.1 point
-
AutoIT Script required which can get self compiled into exe - (Moved)
Danp2 reacted to ModemJunki for a topic
Aha, I am not the original poster, but this latest from you still does not write the line correctly, the previous one wrote the output as: "RunWait(@ComSpec & " /c " & "NET USER IDR-ADMIN " & $Password)" Now with your latest it looks like: "RunWait(@ComSpec & " /c " & "NET USER IDR-ADMIN " newpass1) So I think it needs to be like so, it would work even with what I wrote and eliminate two vars: FileWriteLine($File,'RunWait(@ComSpec & " /c " & "NET USER IDR-ADMIN ' & $Password & '")') So that the output is like: RunWait(@ComSpec & " /c " & "NET USER IDR-ADMIN newpass2") It always messes me up when I have to mix using " " and ' ' to create strings to pass externally.1 point -
GUI doesn't reopen after open/close
Daemante2018 reacted to BrewManNH for a topic
Here's one way to do it. #include <GUIConstantsEx.au3> #include <WindowsConstants.au3> $QG = GUICreate("QG", 337, 588, 284, 164, -1, BitOR($WS_EX_TOPMOST, $WS_EX_WINDOWEDGE)) $File = GUICtrlCreateMenu("File") $New = GUICtrlCreateMenuItem("New", $File) $Open = GUICtrlCreateMenuItem("Open", $File) $Save = GUICtrlCreateMenuItem("Save", $File) $Exit = GUICtrlCreateMenuItem("Exit", $File) $Help = GUICtrlCreateMenu("Help") $About = GUICtrlCreateMenuItem("About", $Help) GUISetFont(12, 400, 0, "MS Sans Serif") GUISetBkColor(0xB4B4B4) GUISetState(@SW_SHOW, $QG) $About1 = GUICreate("About", 246, 288, -1, -1, $WS_SYSMENU, BitOR($WS_EX_TOPMOST, $WS_EX_WINDOWEDGE)) $Version = GUICtrlCreateLabel("Version 1.0", 175, 26, 57, 17) While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $New Case $Open Case $Save Case $Exit Exit Case $About GUISetState(@SW_DISABLE, $QG) _QGAbout($About1) GUISetState(@SW_ENABLE, $QG) EndSwitch WEnd Func _QGAbout($AboutGUI) GUISetState(@SW_SHOW, $AboutGUI) While 1 $nMsg = GUIGetMsg(1) If $nMsg[1] = $AboutGUI Then Switch $nMsg[0] Case $GUI_EVENT_CLOSE GUISetState(@SW_HIDE, $AboutGUI) ExitLoop EndSwitch EndIf WEnd EndFunc ;==>_QGAbout1 point -
Compare/delete text
careca reacted to HurleyShanabarger for a topic
That is not useful at all for this scenario. I came up with a solution using regexp. Any ideas for improvements? On two textfiles with around 2000 lines it needs less then 500ms. #include <Array.au3> $sText = StringReplace("VAR_11|VAR_12|VAR_14|VAR_15", "|", @CRLF) $sFind = StringReplace("VAR_11|VAR_12|VAR_13", "|", @CRLF) $sResult = _Text_FindInOtherText($sText, $sFind) MsgBox(0, "1", "Match exact string" & @CRLF & $sResult) $sText = StringReplace("VAR_11 test|VAR_12 next test|VAR_14 oh yeah|VAR_15", "|", @CRLF) $sFind = StringReplace("VAR_11|VAR_12|VAR_13", "|", @CRLF) $sResult = _Text_FindInOtherText($sText, $sFind, False) MsgBox(0, "2", "Match exact string" & @CRLF & $sResult) $sText = StringReplace("VAR_11 test|VAR_12 next test|VAR_14 oh yeah|VAR_15", "|", @CRLF) $sFind = StringReplace("VAR_11|VAR_12|VAR_13", "|", @CRLF) $sResult = _Text_FindInOtherText($sText, $sFind, True) MsgBox(0, "3", "Match complete string" & @CRLF & $sResult) Func _Text_FindInOtherText(Const ByRef $sText, $sFind, $boMatchLine = False) Local $sResult = "", $sMtch = "" Local $iFind_Tmp If StringRight($sFind, 2) <> @CRLF Then $sFind &= @CRLF If $boMatchLine Then $sFind = StringReplace($sFind, @CRLF, ".*" & @CRLF) ; Use while loop, as pattern is limit so ~30000 characters While 1 $sFind_Tmp = StringLeft($sFind, 20000) $iFind_Tmp = StringInStr($sFind_Tmp, @CRLF, 0, -1) $sFind_Tmp = StringLeft($sFind, $iFind_Tmp - 1) $sFind = StringTrimLeft($sFind, $iFind_Tmp + 1) $sMtch = StringReplace($sFind_Tmp, @CRLF, "|") If StringRight($sMtch, 1) = "|" Then $sMtch = StringTrimRight($sMtch, 1) $sMtch = "(" & $sMtch & ")" $aData = StringRegExp($sText, $sMtch, 3) If Not @error Then $sResult &= _ArrayToString($aData, @CRLF) & @CRLF If StringLen($sFind) = 0 Then ExitLoop WEnd Return StringTrimRight($sResult, 2) EndFunc ;==>_Text_FindInOtherText1 point -
I'm shocked I haven't thought of this before... Anyway, it works fine! Thanks for help and for making my script useless!1 point
-
In many cases, the scrolling will occur automatically once you interact with an element. Why do you want to scroll the view? Again, what's your end goal?1 point
-
How to set an element of a subarray of an array ?
pixelsearch reacted to Malkey for a topic
Here are some examples of dealing with elements of a sub-array which is an element in an array. #include <Array.au3> ; --------- Testing 1D array ---------- Local $b[] = [2, 3, 4], $a[4] = [1, $b, 5, 6] _ArrayDisplay($a, "$a[4] = [1,$b,5,6]") ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF) _ASA($a[1], 1, 7) ConsoleWrite("($a[1])[1] = " & ($a[1])[1] & @CRLF) _ArrayDisplay($a[1], "3 to 7") ; --------- Testing 2D array ---------- Local $b[] = [2, 3, 4], $a[2][4] = [[1, $b, 5, 6], [9, 10, 1, 12]] _ArrayDisplay($a) ConsoleWrite("($a[0][1])[2] = " & ($a[0][1])[2] & @CRLF) ; = 4 ; ($a[0][1])[2] = 7 ; <- this does not work, produces " : error: Statement cannot be just an expression." _ASA($a[0][1], 2, 7) ; In the 2D array of $a item $a[0][1] contains a 1D arr. _ASA() function is used to put the value 7 into ($a[0][1])[2] ConsoleWrite("($a[0][1])[2] = " & ($a[0][1])[2] & @CRLF) ; now = 7 _ArrayDisplay($a[0][1], "4 to 7") ;Assign to Sub-Array (ASA) Func _ASA(ByRef $array, $iIndex, $Value) Local $aTemp = $array ; Copy the array that is stored in an array's element to $aTemp (an array). $aTemp[$iIndex] = $Value ; Assign the new value. $array = $aTemp ; Copy the modified Sub-array back to the element of the main array. EndFunc ;==>_ASA1 point -
Creating a process completion window and .exe error
yasha reacted to FrancescoDiMuro for a topic
@yasha You could do something like this (with a little animation either): Global $intNumberOfProcess = 3, _ $strDots = "." ProgressOn("", "", "", Default, Default, $DLG_MOVEABLE) For $i = 1 To $intNumberOfProcess Step 1 For $j = 10 To 100 Step 10 ProgressSet($j, "Process " & $i & " of " & $intNumberOfProcess & " - " & $j & "% completed.", _ "Installing Software" & $strDots) $strDots &= "." If StringLen($strDots) = 4 Then $strDots = "" Sleep(1000) Next Next ProgressOff()1 point -
Writing a recursive decent parser in Autoit
junkew reacted to TheAutomator for a topic
I'm writing a recursive decent parser in Autoit! The programming language i'm making is called HighLevel. I'm doing this for learning purposes, because it's fun and because I can implement it into my other project: Fullscreen Console With custom programming language! It's not easy... In Autoit you don't have objects like in Java or Visual Basic, so I had to figure out a way to still convert the code to an abstract syntax tree. I used nested array's and array based dictionary's instead of objects. The code is still very dirty and I need to make a lot of modifications but if you're careful with testing you'll see what it can do already. Console window Because this code eventually will get implemented into my console project I crafted a nice little console window (with a custom sci-fi looking theme, yeah i was a little bored haha). {ESC} is your panic button for now, it terminates the script completely. If you get an error while opening a script the text will turn red. To minimize it press the blue button, to close it use the red one, to drag the gui just grab it on one of the sides. The console window will display what you write to it with your "HighLevel-script" and some additional information: How to test it: Download: HighLevel.Au3, Debug.Au3 (includes a function to display nested arrays for debugging), GUI.bmp (for the console) Compile the Autoit code to EXE. The GUI.bmp must be in the same folder as the EXE file! Write a HighLevel-script (text file) and drag it into the compiled autoit-exe. The custom made little console window will pop up in the left top corner of your screen and your HighLevel-script (the text file) will be interpreted and executed. The Language: exit script: Abort show / hide the console: Show Hide write to/clear the console: Write 'this is a ''string''!' Clear variables: test_var_1 = 123 some_list = ['a', 5, true] some_list[1] = 3 math = 1 + 2 * 3 / 4 - -5 & test_var beep (under construction): Beep F, optD wait X seconds: Wait X Messages: Message 'Hello World!' move/click the mouse: Move X, Y Click send keys (under construction): Send 'HighLevel', True if's: If false ElseIf true # this part will run Else End subs: Sub X # do stuff End Call X for loops: For X = 1 to 10 # X iterates End Values: Input 'Give me input' Random YesNo 'yes or no' operators: + - * / & > = ! < ( ) And Not Or Example script: # my first HighLevel script message 'Hello World!' message 'Lets write to the console...' clear # clear the console... list = ['a', 16, true] for i = 0 to 2 write list[i] wait 1 end sub test if YesNo 'would you like to quit?' message 'Goodbye!' abort else write 1 + 2 * 3 & ' math!' end end call test test script.HighLevel GUI.bmp Debug.au3 HighLevel.au31 point -
ALT + MouseWheel up/down to control volume up/down
FrancescoDiMuro reacted to JLogan3o13 for a topic
Wow, giving up after less than three hours - and after someone pointed you directly to a topic that would help you - I am sure you'll do wonderful things in the scripting world1 point -
#include <_MouseClickPlus.au3> $Window = ControlGetHandle("[Active]","","Scintilla1") _MouseClickPlus($Window, "left",974, 776,1) This code is clicking random spot in SCitE1 point
-
That's about as useless as the OP's post, what's not working and where is YOUR code?1 point
-
I whould like to have an UDF like that. Seem like not working1 point
-
https://github.com/pokerregion/pokerstars-autoit/blob/master/MouseClickPlus.au3 I found what looks like the original version of this, although game hackers are using it on various different gaming sites.1 point
-
Can someone lead me to the souce page of this UDF ? Dont find it here https://www.autoitscript.com/wiki/User_Defined_Functions In pm or here . 1000 Thanks before. Edit: So you earn 1thanks1 point
-
Working. You can use SendMessageA, SendMessageW AND SendMessage. But I still do not understand why SendMessage is not reported as a valid function in user32.dll from all the tools I used and all the documents I found on the web. But nothing works with WinGetHandle tho !1 point
-
open notepad and use this code $Window = ControlGetHandle("Untitled - Notepad","","Edit1") _MouseClickPlus($Window, "right",974, 776,1)1 point
-
https://www.win7dll.info/user32_dll.html http://www.softspecialists.com/library/genlib/vistasp1/user32.htm1 point
-
Doesn't matter, assume the UDF is correct for the moment and let the OP post something more than "it doesn't work" without any description or script. Jos1 point
-
strange i got SendMessageA, SendMessageW, but not SendMessage... Maybe it is the tool that I used1 point
-
Hi! Today I want to show you my current AutoIt project: The ISN AutoIt Studio. The ISN AutoIt Studio is a complete IDE made with AutoIt, for AutoIt! It includes a GUI designer, a code editor (with syntax highlighting, auto complete & intelisense), a file viewer, a backup system, trophies and a lot more features!! Here are some screenshots: Here some higlights: -> easy to create/manage/public your AutoIt-projects! ->integrated GUI-Editor (ISN Form Studio 2) ->integrated - file & projectmanager ->auto backupfunction for your Projects ->extendable with plugins! ->available in several languages ->trophies ->Syntax highlighting /Autocomplete / Intelisense ->Dynamic Script ->detailed overview of the project (total working hours, total size...) And much more!!! -> -> Click here to download ISN AutoIt Studio <- <- Here is the link to the german autoit forum where I posted ISN AutoIt Studio the first time: http://autoit.de/index.php?page=Thread&threadID=29742&pageNo=1 For more information visit my Homepage: https://www.isnetwork.at So….have fun with ISN AutoIt Studio! PS: Sorry for my bad English! ^^1 point
-
Real examples sqlite3_get_table sqlite3_get_table returns a 1D or 2D array of result data generated by executing a SQLite SELECT statement. sqlite3_get_table is not coded in SQLite.au3, but _SQLite_GetTable and _SQLite_GetTable2d implements similar functionality. Both _SQLite_GetTable and _SQLite_GetTable2d are based on a technique where the rows are extracted from a database and inserted in a 1D or 2D array one by one. If you extracts 1 GB of data from the database, the array will use 1 GB of memory when all rows are inserted. Because rows are both extracted from the database and inserted in the array one by one, you need pretty much code in the loops that handles the rows. _SQLite_GetTable and _SQLite_GetTable2d uses little memory, but are not very fast because of much code in the loops. sqlite3_get_table extracts all rows from the database at once and inserts the rows in a C-array. Then you have to copy the rows from the C-array to an AutoIt array. If you extracts 1 GB of data from the database, the C-array will use 1 GB of memory. When all rows are inserted in an AutoIt array this will also use 1 GB of memory. When all rows are copied, the C-array can be deleted. But you still need 2 GB of memory to be able to copy the rows. You don't need many code lines to copy data from a C-array to an AutoIt array. Code to copy data can be implemented in a tight and fast loop. sqlite3_get_table uses much memory, but is fast because of a simple loop. The fact that sqlite3_get_table uses much memory is the reason why it's not recommended to use the function. But you can use it if you know what you are doing. In this example sqlite3_get_table is implemented as an AutoIt function. Then the loop to copy data from the C-array to the AutoIt array is optimized with a few lines of C++ code. Installing SQLite Navigate to "Precompiled Binaries for Windows" section here and download the three zip files. Extract sqlite3.dll from sqlite-dll-win64-x64-3170000.zip and rename it to sqlite3_x64.dll Extract sqlite3.dll from sqlite-dll-win32-x86-3170000.zip Extract the 3 files in sqlite-tools-win32-x86-3170000.zip Copy all 5 files to C:\Windows\System32 Copy sqlite3.dll to C:\Windows\SysWOW64 CreateDBs.au3: Create databases The example is stored in Examples\Real examples\sqlite3_get_table folder in zip file in bottom of first post (goto top of second post and scroll up a little bit). The folder contains 7 AutoIt scripts. Run CreateDBs.au3 to create the databases. All databases, 5 in total, contains one table with 10 columns but a different number of rows. The name of a database indicates the number of rows when all rows are created. You can select databases in the GUI. You can set a smaller number of rows in the Stop field (double click). The Created field is updated for every 10,000 rows. You can cancel the creation at any time (checked for every 10,000 rows). You can continue the creation at a later time. It takes about 5 minutes to create all 5 databases and it uses about 140 MB of disk space. Running examples If you've created all tables with the maximum number of rows, the tables contains 10,000, 50,000, 100,000, 500,000 and 1,000,000 rows. For examples 1 - 4 it takes a long time to extract data from the last two tables. Because the examples displays the result array with _ArrayDisplayEx, you can exit an example by clicking the Exit Script button, when the array with 100,000 rows has been displayed. In this way you can skip the last two tables that takes long time. If you're using AutoIt 3.3.10, please read this post. Example1.au3: _SQLite_GetTable2d Example1 extracts data from the tables with _SQLite_GetTable2d: ;#AutoIt3Wrapper_UseX64=y #include <SQLite.au3> #include "..\..\..\Includes\ArrayDisplayEx.au3" Opt( "MustDeclareVars", 1 ) Example( "10000.db" ) Example( "50000.db" ) Example( "100000.db" ) Example( "500000.db" ) Example( "1000000.db" ) Func Example( $sDb ) If Not FileExists( $sDb ) Then Return _SQLite_Startup() _SQLite_Open( $sDb ) Local $hTimer = TimerInit() Local $aResult, $iRows, $iColumns Local $sSQL = "SELECT * FROM lvdata;" ConsoleWrite( "Db = " & $sDb & @CRLF ) _SQLite_GetTable2d( -1, $sSQL, $aResult, $iRows, $iColumns ) ConsoleWrite( "Time = " & TimerDiff( $hTimer ) & @CRLF ) ConsoleWrite( "Rows = " & $iRows & @CRLF & @CRLF ) _ArrayDisplayEx( $aResult ) _SQLite_Close() _SQLite_Shutdown() EndFunc Time measurements on my PC: 32 bit 64 bit ------ ------ Db = 10000.db 10000.db Time = 1867.58359001979 1478.42919526511 Rows = 10000 10000 Db = 50000.db 50000.db Time = 9387.16462453407 7352.46471634831 Rows = 50000 50000 Db = 100000.db 100000.db Time = 18718.1164395137 14667.2645397015 Rows = 100000 100000 Db = 500000.db 500000.db Time = 94108.9009941094 73874.0820654158 Rows = 500000 500000 Db = 1000000.db 1000000.db Time = 188802.773931406 147955.955762936 Rows = 1000000 1000000 Example2.au3: sqlite3_get_table In Example2 _SQLite_GetTable2d is replaced by _SQLite_GetTableEx which implements sqlite3_get_table: Func _SQLite_GetTableEx( $hDB, $sSQL, ByRef $aResult, ByRef $iRows, ByRef $iColumns, $iMaxChars = 256 ) ; Call sqlite3_get_table If __SQLite_hChk($hDB, 2) Then Return SetError(@error, 0, $SQLITE_MISUSE) If $iMaxChars = "" Or $iMaxChars < 1 Or $iMaxChars = Default Then $iMaxChars = 256 Local $tSQL8 = __SQLite_StringToUtf8Struct($sSQL) If @error Then Return SetError(3, @error, 0) Local $avRval = DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_get_table", _ "ptr", $hDB, _ ; An open database "struct*", $tSQL8, _ ; SQL to be executed "ptr*", 0, _ ; Results of the query "int*", 0, _ ; Number of result rows "int*", 0, _ ; Number of result columns "long*", 0) ; Error msg written here If @error Then Return SetError(1, @error, $SQLITE_MISUSE) ; DllCall error ; Copy data $iRows = $avRval[4] $iColumns = $avRval[5] Local $pResult = $avRval[3] Local $iPtrSize = @AutoItX64 ? 8 : 4 Local $tagChars = "char[" & $iMaxChars & "]" If $iColumns = 1 Then Dim $aResult[$iRows+1] ; Add one row for column names For $i = 0 To $iRows $aResult[$i] = DllStructGetData( DllStructCreate( $tagChars, DllStructGetData( DllStructCreate( "ptr", $pResult ), 1 ) ), 1 ) $pResult += $iPtrSize Next Else Dim $aResult[$iRows+1][$iColumns] ; Add one row for column names For $i = 0 To $iRows For $j = 0 To $iColumns - 1 $aResult[$i][$j] = DllStructGetData( DllStructCreate( $tagChars, DllStructGetData( DllStructCreate( "ptr", $pResult ), 1 ) ), 1 ) $pResult += $iPtrSize Next Next EndIf ; Cleanup DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_free_table", "ptr", $avRval[3]) If @error Then Return SetError(1, @error, $SQLITE_MISUSE) ; DllCall error EndFunc Note the loops to copy data from the C-array to the AutoIt array. There are two loops for 1D and 2D arrays. These loops are tight and fast loops: 32 bit 64 bit ------ ------ Db = 10000.db 10000.db Time = 483.665432687752 406.576381743318 Rows = 10000 10000 Db = 50000.db 50000.db Time = 2424.12387220034 2031.13843558957 Rows = 50000 50000 Db = 100000.db 100000.db Time = 4816.86633631272 3969.70711978683 Rows = 100000 100000 Db = 500000.db 500000.db Time = 24276.2591765753 20212.6546837174 Rows = 500000 500000 Db = 1000000.db 1000000.db Time = 48510.3322877481 40355.7039802608 Rows = 1000000 1000000 Example3.au3: General usage of the UDF Example3 shows the general usage of the UDF (AccessingVariables.au3). AccessVariables05 is called with the method function GetTableData and 5 parameters. Especially the code in SQLite_GetTableEx is reorganized to fit into the UDF. Full code in Example3.au3: ;#AutoIt3Wrapper_UseX64=y Global $g_hDll_SQLite = 0 ; AutoIt v3.3.10 Global $__g_hDll_SQLite = 0 ; AutoIt v3.3.12/14 #include <SQLite.au3> #include "..\..\..\Includes\AccessingVariables.au3" #include "..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\Includes\ArrayDisplayEx.au3" Opt( "MustDeclareVars", 1 ) Example( "10000.db" ) Example( "50000.db" ) Example( "100000.db" ) Example( "500000.db" ) Example( "1000000.db" ) Func Example( $sDb ) If Not FileExists( $sDb ) Then Return _SQLite_Startup() If $g_hDll_SQLite Then $__g_hDll_SQLite = $g_hDll_SQLite _SQLite_Open( $sDb ) Local $hTimer = TimerInit() Local $pResult, $iRows, $iColumns Local $sSQL = "SELECT * FROM lvdata;" ConsoleWrite( "Db = " & $sDb & @CRLF ) Local $hTimer2 = TimerInit() _SQLite_GetTableEx( -1, $sSQL, $pResult, $iRows, $iColumns ) ConsoleWrite( "Time (SQLite) = " & TimerDiff( $hTimer2 ) & @CRLF ) $iRows += 1 ; Add one row for column names Local $aResult Local $iMaxChars = 10 AccessVariables05( GetTableData, $aResult, $pResult, $iRows, $iColumns, $iMaxChars ) _SQLite_FreeTable( $pResult ) ConsoleWrite( "Time (total) = " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aResult ) _SQLite_Close() _SQLite_Shutdown() EndFunc Func GetTableData( $vaResult, $vpResult, $viRows, $viColumns, $viMaxChars ) ; Convert variants to AutoIt variables Local $pResult = Ptr( AccVars_VariantToVariable( $vpResult ) ) Local $iRows = AccVars_VariantToVariable( $viRows ) Local $iColumns = AccVars_VariantToVariable( $viColumns ) Local $iMaxChars = AccVars_VariantToVariable( $viMaxChars ) Local $iElements = $iRows * $iColumns ; Create SAFEARRAYBOUND structure for two dimensions Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND & ( $iColumns > 1 ? $tagSAFEARRAYBOUND : "" ) ), $i = 0 If $iColumns > 1 Then DllStructSetData( $tSafeArrayBound, 1, $iColumns ) ; Dimension 2: Elements DllStructSetData( $tSafeArrayBound, 2, 0 ) ; Lower bound $i = 2 EndIf DllStructSetData( $tSafeArrayBound, $i+1, $iRows ) ; Dimension 1: Elements DllStructSetData( $tSafeArrayBound, $i+2, 0 ) ; Lower bound ; Create safearray of BSTRs with one or two dimensions Local $pSafeArray = SafeArrayCreate( $VT_BSTR, $iColumns > 1 ? 2 : 1, $tSafeArrayBound ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; Character buffer Local $tagChars = "char[" & $iMaxChars & "]" ; Pointer size Local $iPtrSize = @AutoItX64 ? 8 : 4 ; Fill safearray Local $hTimer = TimerInit() For $i = 0 To $iElements - 1 DllStructSetData( DllStructCreate( "ptr", $pSafeArrayData ), 1, SysAllocString( DllStructGetData( DllStructCreate( $tagChars, DllStructGetData( DllStructCreate( "ptr", $pResult ), 1 ) ), 1 ) ) ) $pSafeArrayData += $iPtrSize $pResult += $iPtrSize Next ConsoleWrite( "Time (loop) = " & TimerDiff( $hTimer ) & @CRLF ) SafeArrayUnaccessData( $pSafeArray ) ; --- Set $vaResult to match an array of basic strings --- ; Set vt element to $VT_ARRAY + $VT_BSTR Local $tvt = DllStructCreate( "word", $vaResult ) DllStructSetData( $tvt, 1, $VT_ARRAY + $VT_BSTR ) ; <<<< Not a proper AutoIt array >>>> ; This is an array of basic strings and not variants as a usual AutoIt array ; Set data element to safearray pointer Local $pData = $vaResult + 8 Local $tData = DllStructCreate( "ptr", $pData ) DllStructSetData( $tData, 1, $pSafeArray ) ; <<<< On function exit the safearray contained in a variant is converted to a native AutoIt array >>>> EndFunc Func _SQLite_GetTableEx( $hDB, $sSQL, ByRef $pResult, ByRef $iRows, ByRef $iColumns ) If __SQLite_hChk($hDB, 2) Then Return SetError(@error, 0, $SQLITE_MISUSE) Local $tSQL8 = __SQLite_StringToUtf8Struct($sSQL) If @error Then Return SetError(3, @error, 0) Local $avRval = DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_get_table", _ "ptr", $hDB, _ ; An open database "struct*", $tSQL8, _ ; SQL to be executed "ptr*", 0, _ ; Results of the query "int*", 0, _ ; Number of result rows "int*", 0, _ ; Number of result columns "long*", 0) ; Error msg written here If @error Then Return SetError(1, @error, $SQLITE_MISUSE) ; DllCall error $pResult = $avRval[3] $iRows = $avRval[4] $iColumns = $avRval[5] EndFunc Func _SQLite_FreeTable( $pTable ) DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_free_table", "ptr", $pTable) If @error Then Return SetError(1, @error, $SQLITE_MISUSE) ; DllCall error EndFunc The purpose of the UDF is to be able to use a safearray instead of a native AutoIt array. A safearray can be accessed by a function coded in assembler, C, C++, C# or FreeBasic which a native AutoIt array can't. In Example3 data is copied from the C-array to a safearray with pure AutoIt code. In first place the loop to fill the safearray uses much more time than the loops in Example2. When data is copied, the safearray is converted to a native AutoIt array, and the C-array is deleted. Time measurements: 32 bit 64 bit ------ ------ Db = 10000.db 10000.db Time (SQLite) = 23.1510956480495 15.8646911922054 Time (loop) = 1259.64312687043 996.176992582274 Time (total) = 1332.95543768019 1052.21221334371 Db = 50000.db 50000.db Time (SQLite) = 114.037493676343 76.4651352473028 Time (loop) = 6349.05395873402 5002.66300074637 Time (total) = 6711.25392094445 5282.21047901322 Db = 100000.db 100000.db Time (SQLite) = 173.200050312207 134.708718363014 Time (loop) = 12620.353116337 10034.0305563544 Time (total) = 13289.4445210948 10571.7439330294 Db = 500000.db 500000.db Time (SQLite) = 860.637402471615 672.991986063297 Time (loop) = 64303.8053870632 52010.5345339555 Time (total) = 67677.4638436421 54740.0105611307 Db = 1000000.db 1000000.db Time (SQLite) = 1712.64277058465 1333.27875456231 Time (loop) = 143114.724853732 119586.97418064 Time (total) = 149859.375441548 125065.107209883 Example4.au3: Simplified usage of the UDF Because only one safearray and one AutoIt array is involved, we can use AccVars_SafeArrayToArray in AccVarsUtilities.au3 to perform the conversion. We don't need to use one of the AccessVariablesXY functions and we don't need to implement a method function or handle variants: ;#AutoIt3Wrapper_UseX64=y Global $g_hDll_SQLite = 0 ; AutoIt v3.3.10 Global $__g_hDll_SQLite = 0 ; AutoIt v3.3.12/14 #include <SQLite.au3> #include "..\..\..\Includes\AccVarsUtilities.au3" #include "..\..\..\Includes\ArrayDisplayEx.au3" Opt( "MustDeclareVars", 1 ) Example( "10000.db" ) Example( "50000.db" ) Example( "100000.db" ) Example( "500000.db" ) Example( "1000000.db" ) Func Example( $sDb ) If Not FileExists( $sDb ) Then Return _SQLite_Startup() If $g_hDll_SQLite Then $__g_hDll_SQLite = $g_hDll_SQLite _SQLite_Open( $sDb ) Local $hTimer = TimerInit() Local $pResult, $iRows, $iColumns Local $sSQL = "SELECT * FROM lvdata;" ConsoleWrite( "Db = " & $sDb & @CRLF ) Local $hTimer2 = TimerInit() _SQLite_GetTableEx( -1, $sSQL, $pResult, $iRows, $iColumns ) ConsoleWrite( "Time (SQLite) = " & TimerDiff( $hTimer2 ) & @CRLF ) $iRows += 1 ; Add one row for column names ; Create SAFEARRAYBOUND structure for two dimensions Local $tSafeArrayBound = DllStructCreate( $tagSAFEARRAYBOUND & ( $iColumns > 1 ? $tagSAFEARRAYBOUND : "" ) ), $i = 0 If $iColumns > 1 Then DllStructSetData( $tSafeArrayBound, 1, $iColumns ) ; Dimension 2: Elements DllStructSetData( $tSafeArrayBound, 2, 0 ) ; Lower bound $i = 2 EndIf DllStructSetData( $tSafeArrayBound, $i+1, $iRows ) ; Dimension 1: Elements DllStructSetData( $tSafeArrayBound, $i+2, 0 ) ; Lower bound ; Create safearray of BSTRs with one or two dimensions Local $pSafeArray = SafeArrayCreate( $VT_BSTR, $iColumns > 1 ? 2 : 1, $tSafeArrayBound ) ; Pointer to data Local $pSafeArrayData SafeArrayAccessData( $pSafeArray, $pSafeArrayData ) ; Character buffer Local $iMaxChars = 10 Local $tagChars = "char[" & $iMaxChars & "]" ; Pointer size Local $iPtrSize = @AutoItX64 ? 8 : 4 ; Fill safearray Local $pResult0 = $pResult Local $hTimer3 = TimerInit() For $i = 0 To $iRows * $iColumns - 1 DllStructSetData( DllStructCreate( "ptr", $pSafeArrayData ), 1, SysAllocString( DllStructGetData( DllStructCreate( $tagChars, DllStructGetData( DllStructCreate( "ptr", $pResult ), 1 ) ), 1 ) ) ) $pSafeArrayData += $iPtrSize $pResult += $iPtrSize Next ConsoleWrite( "Time (loop) = " & TimerDiff( $hTimer3 ) & @CRLF ) SafeArrayUnaccessData( $pSafeArray ) _SQLite_FreeTable( $pResult0 ) ; AutoIt array Local $aResult AccVars_SafeArrayToArray( $pSafeArray, $aResult ) ConsoleWrite( "Time (total) = " & TimerDiff( $hTimer ) & @CRLF & @CRLF ) _ArrayDisplayEx( $aResult ) _SQLite_Close() _SQLite_Shutdown() EndFunc 32 bit 64 bit ------ ------ Db = 10000.db 10000.db Time (SQLite) = 17.4150607486656 14.1043180396414 Time (loop) = 1324.75255315058 1029.05446850528 Time (total) = 1391.56528036588 1083.47476715366 Db = 50000.db 50000.db Time (SQLite) = 95.3244555559804 82.5873772878063 Time (loop) = 6532.85558900468 5074.77180809772 Time (total) = 6874.98857170404 5363.29347697801 Db = 100000.db 100000.db Time (SQLite) = 171.70619887396 137.223220524278 Time (loop) = 13226.8659429023 10330.4403814197 Time (total) = 13889.9586697408 10871.0854969522 Db = 500000.db 500000.db Time (SQLite) = 854.537047349439 683.296291801936 Time (loop) = 67230.8330161115 53188.3987142682 Time (total) = 70543.9902123918 55966.6529250066 Db = 1000000.db 1000000.db Time (SQLite) = 1713.11098440709 1361.08095887974 Time (loop) = 151801.206107725 123302.690816526 Time (total) = 158540.361416743 128827.087527172 Example5.au3: C++ code In Example5 the loop to copy data from the C-array to the safearray is replaced by C++ code. This is the loop in Example4: ; Fill safearray Local $pResult0 = $pResult Local $hTimer3 = TimerInit() For $i = 0 To $iRows * $iColumns - 1 DllStructSetData( DllStructCreate( "ptr", $pSafeArrayData ), 1, SysAllocString( DllStructGetData( DllStructCreate( $tagChars, DllStructGetData( DllStructCreate( "ptr", $pResult ), 1 ) ), 1 ) ) ) $pSafeArrayData += $iPtrSize $pResult += $iPtrSize Next ConsoleWrite( "Time (loop) = " & TimerDiff( $hTimer3 ) & @CRLF ) In Example5 the loop is replaced by a DllCall: ; Fill safearray Local $hTimer3 = TimerInit() Local $hGetTableDll = DllOpen( @AutoItX64 ? "GetTable_x64.dll" : "GetTable.dll" ) DllCall( $hGetTableDll, "int:cdecl", "GetTable", "int", $iRows * $iColumns, "ptr", $pResult, "ptr", $pSafeArrayData, "int", 256 ) ConsoleWrite( "Time (loop) = " & TimerDiff( $hTimer3 ) & @CRLF ) DllClose( $hGetTableDll ) The Dll-files (8 and 9 KB) are included in the zip-file. And this is the C++ code: #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <OleAuto.h> extern "C" __declspec(dllexport) int __cdecl GetTable( int iElements, char **pResult, BSTR *pSafeArrayData, int iMaxChars ) { int iCharSize; BSTR sBuffer; for ( int i = 0; i < iElements; i++ ) { iCharSize = MultiByteToWideChar( CP_UTF8, 0, pResult[i], -1, NULL, 0 ); if ( iCharSize > iMaxChars ) { iCharSize = iMaxChars; } sBuffer = SysAllocStringLen( NULL, iCharSize ); MultiByteToWideChar( CP_UTF8, 0, pResult[i], -1, sBuffer, iCharSize ); pSafeArrayData[i] = sBuffer; } return 0; } It's not much code but it makes a big difference. At this point we can really see some performance improvements: 32 bit 64 bit ------ ------ Db = 10000.db 10000.db Time (SQLite) = 17.879859753638 13.0433770827516 Time (loop) = 14.2736909526912 10.4447857519625 Time (total) = 91.6964756674335 65.9479816314499 Db = 50000.db 50000.db Time (SQLite) = 84.786660638378 79.0254340589442 Time (loop) = 63.1917572018103 45.9053071102778 Time (total) = 400.493344503398 331.284103048275 Db = 100000.db 100000.db Time (SQLite) = 179.167608586765 134.67712087162 Time (loop) = 133.477003851899 91.1557027167192 Time (total) = 812.997001369663 628.453799373235 Db = 500000.db 500000.db Time (SQLite) = 877.786144244536 677.600973834568 Time (loop) = 593.045083620342 441.694591827236 Time (total) = 3930.40734165769 3169.40903933015 Db = 1000000.db 1000000.db Time (SQLite) = 1709.34257301543 1340.73765641414 Time (loop) = 1177.70597022203 887.914832692828 Time (total) = 7898.99402933472 6350.2593604695 Example6.au3: Safearray only SafeArrayDisplay was introduced in the previous post. The old version was only able to handle integers ($VT_I4). The new version can also handle strings ($VT_BSTR). We can replace _ArrayDisplayEx with SafeArrayDisplay, and we don't need to convert the safearray to a native AutoIt array. This halves the total execution time: 32 bit 64 bit ------ ------ Db = 10000.db 10000.db Time (SQLite) = 17.3684525471736 20.9012069874957 Time (loop) = 14.0346094688457 19.0544895236322 Time (total) = 36.3534062047047 44.0450149155818 Db = 50000.db 50000.db Time (SQLite) = 104.392450455003 79.7554221353439 Time (loop) = 62.9584934597501 47.4223525396382 Time (total) = 191.106722871593 146.179073416577 Db = 100000.db 100000.db Time (SQLite) = 203.835110791966 158.260029786838 Time (loop) = 120.158807728621 93.6750619450983 Time (total) = 370.362151655785 289.398301441027 Db = 500000.db 500000.db Time (SQLite) = 895.89982181088 728.70761913627 Time (loop) = 587.891118469169 441.994344046843 Time (total) = 1716.73969317784 1362.86419063576 Db = 1000000.db 1000000.db Time (SQLite) = 1780.12814545906 1427.71566645834 Time (loop) = 1186.23090118482 878.533031475645 Time (total) = 3438.9228534195 2694.91928298826 Note that the UDF (AccessingVariables.au3) is not included in Example6. The UDF is used for conversions between AutoIt arrays and safearrays. Since there are no conversions the UDF is not used.1 point
-
Array variables SafeArrayDisplay.au3 When the number of array elements exceeds one million the conversions between native AutoIt arrays and safearrays starts taking longer time. In some situations you may use a safearray throughout the code without the need to convert to a native AutoIt array at all. This means that you can skip the conversions completely. Or maybe you need more array elements than are supported by native AutoIt arrays. There is a limit around 16 million elements. There isn't such a limit for safearrays. In these situations you create the safearray with SafeArrayCreate function and fills out and manipulates the safearray directly. With recent updates in _ArrayDisplayEx based on virtual ListView it's easy to create a SafeArrayDisplay UDF to display the contents of a safearray in a virtual listview. In this very early version only safearrays of integers are supported. Safearrays of integers Examples\Demo examples\6) Safearrays of integers\ in the zip file in bottom of first post (goto top of second post and scroll up a little bit) contains five examples. Example 1 is about a native AutoIt array. Examples 2 - 5 is all about safearrays. Example1.au3 is a copy of the example in the code box in top of first post. A few timers are added to measure the execution time for different parts of the code. On my PC the 1D safearray of 16 million integers is filled out in about 25 milli seconds. Conversion to a native AutoIt array takes about 765 milli seconds (pretty fast because a safearray of integers is a very simpel array). The listview (_ArrayDisplayEx) shows up in less than 800 milli seconds. In Example2.au3 a 1D safearray of 100 million integers shows up in the listview (SafeArrayDisplay) in about 200 milli seconds. Assembler code is the same as in example 1. No conversions. In Example3.au3 a 2D safearray of 10 million rows and 10 columns (100 million elements) shows up in about 200 milli seconds. Assembler code in Example3-x86/x64.asm. Example4.au3: 50 million rows, 10 columns = 500 million elements. About 1 second. Example5.au3 must be run as 64 bit code and you need at least 8 GB RAM: 100 million rows, 10 columns = 1,000 million (one billion) elements. About 2 seconds.1 point
-
In posts 15 - 17 it's demonstrated how it's possible to replace RectToVariant and VariantToRect methods of the UIAutomation object with our own methods. The purpose is to be able to access the variables inside the method functions. Particularly native AutoIt arrays can be accessed as safearrays. The original methods are executed inside our own methods. The UIAutomation object is created with ObjCreateInterface. This technique can also be applied to objects created with ObjCreate eg. the Dictionary object. Here it's demonstrated with the Items method which returns an array. ItemsInit replaces the original Items method with our own method: Func ItemsInit() Static $pItemsOrg = 0 If $pItemsOrg Then Return ; ItemsInit should be called only once _WinAPI_CoInitialize( $COINIT_APARTMENTTHREADED ) ; Check Dictionary object in Registry for $COINIT_APARTMENTTHREADED Local $tIDispatch = _WinAPI_GUIDFromString( "{00020400-0000-0000-C000-000000000046}" ) Local $sCLSID = _WinAPI_CLSIDFromProgID( "Scripting.Dictionary" ) Local $tCLSID = _WinAPI_GUIDFromString( $sCLSID ) Local $oDict ; Create Dictionary object CoCreateInstance( $tCLSID, 0, 1, $tIDispatch, $oDict ) ; 1 = $CLSCTX_INPROC_SERVER ; Replace original Items with new method ; And get original Items function pointer Local $pItemsNew = DllCallbackGetPtr( DllCallbackRegister( "Items", "long", "ptr" ) ) $pItemsOrg = ReplaceVTableFuncPtr( Ptr( $oDict ), 13 * ( @AutoItX64 ? 8 : 4 ), $pItemsNew ) ; 13 is the zero based number of Items method in IDictionary VTable ; This includes the methods of IUnknown (3) and IDispatch (4) ; Initialize Items by passing $pItemsOrg to the function Items( $pItemsOrg ) _WinAPI_CoUninitialize() EndFunc To get a pointer to the object it's necessary to create the object with CoCreateInstance function. The pointer is needed to replace the original Items method in the VTable with our own method. When ItemsInit is executed we can run the example: Global $aItems Example1() Func Example1() ; Create Dictionary object Local $oDict = ObjCreate( "Scripting.Dictionary" ) $oDict.Add( "Key1", "Item1" ) $oDict.Add( "Key2", "Item2" ) $oDict.Add( "Key3", "Item3" ) $oDict.Items() ; Pass $aItems as global _ArrayDisplay( $aItems ) EndFunc In this implementation a global array is needed to pass the array returned by Items method back to the function. Our own Items method is coded in this way: Func Items( $pSelf ) Static $pItemsOrg = 0 If $pItemsOrg = 0 Then $pItemsOrg = $pSelf Return EndIf ; Create variant to store array Local $tArray = DllStructCreate( $tagVARIANT ) Local $pArray = DllStructGetPtr( $tArray ) ; Execute original Items method DllCallAddress( "long", $pItemsOrg, "ptr", $pSelf, "ptr", $pArray ) ; Inspect $pArray as variable ConsoleWrite( "Inspect variable $pArray" & @CRLF ) ConsoleWrite( "------------------------" & @CRLF ) InspectVariableMtd( $pArray ) ConsoleWrite( @CRLF ) ; Inspect $pArray as array ConsoleWrite( "Inspect array $pArray" & @CRLF ) ConsoleWrite( "---------------------" & @CRLF ) InspectArrayMtd( $pArray ) ConsoleWrite( @CRLF ) ; Print elements in $pArray ConsoleWrite( "Elements in $pArray" & @CRLF ) ConsoleWrite( "-------------------" & @CRLF ) Local $pSafeArray = DllStructGetData( DllStructCreate( "ptr", $pArray + 8 ), 1 ) PrintSafeArray1D( $pSafeArray ) ConsoleWrite( @CRLF ) ; Store safearray in $aItems (global) AccVars_SafeArrayToArray( $pSafeArray, $aItems ) EndFunc Output in SciTE console: Inspect variable $pArray ------------------------ ptr = 0x02CF12F8 ($pVariant) vt = 0x200C (VT_ARRAY+VT_VARIANT, array of variants, safearray) data = 0x02AC9C88 (pointer to safearray) Inspect array $pArray --------------------- Number of dimensions = 1 Features flags = 0x00000880 ($FADF_VARIANT+$FADF_HAVEVARTYPE, array of variants) Variant type = 0x000C (VT_VARIANT, variant data type) Size of array element (bytes) = 16 (size of the variant structure) Number of locks = 0 Pointer to data = 0x02AB8E68 (pvData) Dimension 1: Elements in dimension = 3 Lower bound of dimension = 0 Elements in $pArray ------------------- Item1 Item2 Item3 To get an example like this to work it's essential that internal AutoIt code related to COM objects is working properly. This is not the case for AutoIt 3.3.14. The example is not working in AutoIt 3.3.14. You need AutoIt 3.3.10 or 3.3.12. Examples\Subclassing\3) Dictionary object\1 point
-
Please stop bumping and showing little effort. #include <APIConstants.au3> #include <WinAPIEx.au3> While 1 If _IsLocked() Then ConsoleWrite('Workstation Is Locked.' & @CRLF) Else ConsoleWrite('Workstation Not Locked.' & @CRLF) EndIf Sleep(500) WEnd Func _IsLocked() Local $fIsLocked = False Local Const $hDesktop = _WinAPI_OpenDesktop('Default', $DESKTOP_SWITCHDESKTOP) If @error = 0 Then $fIsLocked = Not _WinAPI_SwitchDesktop($hDesktop) _WinAPI_CloseDesktop($hDesktop) EndIf Return $fIsLocked EndFunc ;==>_IsLocked1 point