Jump to content

Recommended Posts

Function arguments that are not ByRef are copies of the original argument send to the function right?
so wouldn't using ByRef be better for memory management and speed most of the time? Especially with large arrays or big strings that need to be passed around.
A lot of examples and functions in autoit don't use byref by default.

Share this post


Link to post
Share on other sites
2 hours ago, TheAutomator said:

Function arguments that are not ByRef are copies of the original argument send to the function right?

[...]

A lot of examples and functions in autoit don't use byref by default.

Yes, but ByRef is not always required for arrays to avoid local copies ! This is described very comprehensively in Global,_Local,_Static_and_ByRef

Excerpt :

"It was mentioned earlier that when you pass variables to functions AutoIt makes local copies of these variables unless you declare that they are to be passed ByRef. In the special case of arrays, which are typically larger than a simple variable, AutoIt will only make a local copy if you change the array inside the function - merely accessing the array will use the original version. So passing the array ByRef is only advantageous if you intend to modify the array within the function - however, it does no harm to force the issue by using the keyword. "

Full text :

Spoiler

Passing variables as parameters using ByRef

When you call a function in AutoIt, you can pass parameters to the function by including them in the parentheses following the function name like this - Function(Parameter_1, Parameter_2). Passing variables in this way means that you can use variables that have been declared as Local within other functions. Note that the parameters are automatically declared as Local variables within the called function and so do not need to be declared again in the code.

Variables can be passed as parameters to a function in 2 ways:

By Value - This is the default. The parameter is treated as a Local variable within the function to which it is passed and any changes made to it are lost when the function ends. So no changes are made to the Local variable within the original function.

By Reference - This is used when ByRef is added before the variable name in the parameter list of the function declaration. Now any changes to the variable made in the function to which it is passed also affect the Local variable in the original function. If you do not understand why this is such a powerful capability, you need to read the Global/Local section again!

Here is a small example to show how parameters are passed when calling a function:


#include <MsgBoxConstants.au3> ; only required for MsgBox constants

Func_A()

Func Func_A()
	; Declare variables
	Local $iVar_A1 = 10
	Local $iVar_A2 = 20
	; And read them
	MsgBox($MB_SYSTEMMODAL, "Read", "Initial read in Func A:" & @CRLF & "Var A1 = " & $iVar_A1 & @CRLF & "Var A2 = " & $iVar_A2)

	; Now pass these variables to another function - we use the names we have already declared in this function
	Func_B($iVar_A1, $iVar_A2)

	; We changed the parameters in Func_B - but nothing happened to the variables in this function
	MsgBox($MB_SYSTEMMODAL, "Read", "Second read in Func A:" & @CRLF & "Var A1 = " & $iVar_A1 & @CRLF & "Var A2 = " & $iVar_A2)
EndFunc   ;==>Func_A

Func Func_B($iVar_B1, $iVar_B2) ; There is no need to declare the variables as parameters are automatically Local in scope
	; Now read these variables - note that they have the same value as the variables in Func_A
	MsgBox($MB_SYSTEMMODAL, "Read", "Initial read in Func B:" & @CRLF & "Var B1 = " & $iVar_B1 & @CRLF & "Var B2 = " & $iVar_B2)

	; Let us change them
	$iVar_B1 = 100
	$iVar_B2 = 200

	; And confirm that they have changed
	MsgBox($MB_SYSTEMMODAL, "Read", "Second read in Func B:" & @CRLF & "Var B1 = " & $iVar_B1 & @CRLF & "Var B2 = " & $iVar_B2)

	; Now return to the other function
EndFunc   ;==>Func_B

As you can see, the Local variables within Func_A are read perfectly by Func_B when passed as parameters, even though they were declared as Local in Func_A. However, although Func_B changes the value of the variables, the values of the original variables within Func_A are not changed.

If we want to change the value of the variables in Func_A from within Func_B, we need to use the ByRef keyword as explained above and illustrated here:


#include <MsgBoxConstants.au3> ; only required for MsgBox constants

Func_A()

Func Func_A()
	; Declare variables
	Local $iVar_A1 = 10
	Local $iVar_A2 = 20

	; And read them
	MsgBox($MB_SYSTEMMODAL, "Read", "Initial read in Func A:" & @CRLF & "Var A1 = " & $iVar_A1 & @CRLF & "Var A2 = " & $iVar_A2)

	; Now pass these variables to another function - but this time we will pass $iVar_A2 By Reference
	Func_B($iVar_A1, $iVar_A2)

	; We changed the parameters in Func_B - this time we see that we have changed $iVar_A2
	MsgBox($MB_SYSTEMMODAL, "Read", "Second read in Func A:" & @CRLF & "Var A1 = " & $iVar_A1 & @CRLF & "Var A2 = " & $iVar_A2)
EndFunc   ;==>Func_A

Func Func_B($iVar_B1, ByRef $iVar_B2) ; Note the ByRef keyword in the function declaration for the second parameter
	; Now read these variables - they have the same value as the variables in Func_A
	MsgBox($MB_SYSTEMMODAL, "Read", "Initial read in Func B:" & @CRLF & "Var B1 = " & $iVar_B1 & @CRLF & "Var B2 = " & $iVar_B2)

	; Let us change them
	$iVar_B1 = 100
	$iVar_B2 = 200

	; And confirm that they have changed
	MsgBox($MB_SYSTEMMODAL, "Read", "Second read in Func B:" & @CRLF & "Var B1 = " & $iVar_B1 & @CRLF & "Var B2 = " & $iVar_B2)

	; Now return to the other function
EndFunc   ;==>Func_B

A couple of more advanced points:

- It was mentioned earlier that when you pass variables to functions AutoIt makes local copies of these variables unless you declare that they are to be passed ByRef. In the special case of arrays, which are typically larger than a simple variable, AutoIt will only make a local copy if you change the array inside the function - merely accessing the array will use the original version. So passing the array ByRef is only advantageous if you intend to modify the array within the function - however, it does no harm to force the issue by using the keyword.

- If you are dealing with a simple variable of considerable size (the text of a file for example) then passing it ByRef is a sensible action. But if you want to make sure that the variable cannot be altered inside the function, you can declare it as Const ByRef in the function definition as shown here:


Local $sString = "A very large chunk of data which we do not want to change"

Foo($sString)

Func Foo(Const ByRef $sText) ; The data is not copied, but also cannot be changed
	; Uncomment this line to see what happens when we try
	;$sText = "New value"
EndFunc   ;==>Foo

ByRef is a very powerful feature - but use it carefully, or you may find that you have changed a variable when you did not want to!

 

 

Edited by Musashi
insert a spoiler instead of a quote

Musashi-C64.png

"In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move."

Share this post


Link to post
Share on other sites

Different syntaxes, different ways to waste cycles.  In order of increasing waste:

Global $hTimer, $bBoolean, $iMax = 5000000

$hTimer = TimerInit()
For $i = 1 To $iMax
    $bBoolean = 0
Next
ConsoleWrite("1. Time = " & TimerDiff($hTimer) & @CRLF)

$hTimer = TimerInit()
For $i = 1 To $iMax
    $bBoolean = False
Next
ConsoleWrite("2. Time = " & TimerDiff($hTimer) & @CRLF)

$hTimer = TimerInit()
For $i = 1 To $iMax
    $bBoolean = Not True
Next
ConsoleWrite("3. Time = " & TimerDiff($hTimer) & @CRLF)

$hTimer = TimerInit()
For $i = 1 To $iMax
    $bBoolean = Not(True)
Next
ConsoleWrite("4. Time = " & TimerDiff($hTimer) & @CRLF)

$hTimer = TimerInit()
For $i = 1 To $iMax
    $bBoolean = (1 = 0)
Next
ConsoleWrite("5. Time = " & TimerDiff($hTimer) & @CRLF)

AutoIt being an interpreter, it's quite logical that the more involved an expression is, the more work it requires at every invokation.


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

I will add that readability is important.
For example: $MB_OKCANCEL (1) "OK and Cancel". Using 1 will be faster but less readable.
Nowadays, speed, flip-flops, however you look at it, is not as the 286 CPU era.
So these questions are good but do not sacrifice readability. Today's CPUs are quite fast :) 

Edited by argumentum

Share this post


Link to post
Share on other sites
49 minutes ago, jchd said:

Different syntaxes, different ways to waste cycles.  In order of increasing waste:

AutoIt being an interpreter, it's quite logical that the more involved an expression is, the more work it requires at every invokation.

hmm, strange..

1. Time = 4513.5517
2. Time = 4327.9589
3. Time = 5918.9678
4. Time = 7456.2174
5. Time = 8699.0866

test 2 has to first convert False to 0 according to a previous answer, but it takes less time?

Edited by TheAutomator

Share this post


Link to post
Share on other sites
7 hours ago, Musashi said:

Yes, but ByRef is not always required for arrays to avoid local copies ! This is described very comprehensively in Global,_Local,_Static_and_ByRef

Excerpt :

"It was mentioned earlier that when you pass variables to functions AutoIt makes local copies of these variables unless you declare that they are to be passed ByRef. In the special case of arrays, which are typically larger than a simple variable, AutoIt will only make a local copy if you change the array inside the function - merely accessing the array will use the original version. So passing the array ByRef is only advantageous if you intend to modify the array within the function - however, it does no harm to force the issue by using the keyword. "

How did i miss that? 😅
Thanks for the research!

Share this post


Link to post
Share on other sites
Just now, argumentum said:

...yeah, CPUs "cheat". If a calculation is been done more than a few times, is just replied without the calculation as the answer is known, so, follow the logic. ;) 

nice, didn't know that,
but then it has to be the same for the other ones right? especially for the more easy one (1)

Share this post


Link to post
Share on other sites

May 12-y old CPU(*) has different timings:

1. Time = 1346.66836591923
2. Time = 1419.11255965179
3. Time = 2037.54539549819
4. Time = 2592.13496621027
5. Time = 3133.78265580193

EDIT:
(*) Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz
Please don't laugh!

Edited by jchd

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites
4 minutes ago, TheAutomator said:

then it has to be the same for the other ones right?

..is a muti-threaded OS. It all depends on what the OS gives as a time slice at the time. Hence, follow the logic. Can't go wrong there.

Edit: here are my results on a 8700k

1. Time = 632.262649350649
2. Time = 673.552346320346
3. Time = 1034.81406060606
4. Time = 1296.44993939394
5. Time = 1536.13021645022

 

Edited by argumentum

Share this post


Link to post
Share on other sites

my I5-9300H @ 2.40GHz gives

1. Time = 702.5235
2. Time = 734.4926
3. Time = 1118.7819
4. Time = 1427.0543
5. Time = 1712.4993
 

Share this post


Link to post
Share on other sites

My new 256-cubit quantum computer gives Time = 0.0 for all five.:geek: What gives?:huh:

Share this post


Link to post
Share on other sites

...another thing to keep in mind is the time it takes for ...something else. A PC is as fast as the slowest thing.
Say that a disk write, in a slow disk, goes on while your loop is running, in the middle of it. The slice of time is gonna be longer, due to the process writing to disk.

So you may have a fast CPU but a slow HDD will be the bottle neck. Therefore, for some stuff I use a RAM disk. If you have a NVMe drive then ... :thumbsup:

Knowing software without understanding hardware will not do for a purist/perfectionist. I come from hardware then software came into existence. I guess that in a computer holy book would start with "In the beginning there was nothing, then a guy created a cable permitting electric potentials to flow..:D

It's handy to understand the hardware the software runs on. Otherwise is a mysterious enterprise.

Share this post


Link to post
Share on other sites

Argumentum,

I do my best to learn as much as possible and yes i still have much to learn, i'm sure you know not everyone on this forum started as a computer scientist 😉
Everything i know i had to teach myself, everything i code i want to program as smooth and efficient as possible.
Focusing on even the little details.. that's what i mean with perfectionism.

Sometimes the more you learn, the more you discover how little you know, so I'm grateful for all the tips and help :)

Edited by TheAutomator

Share this post


Link to post
Share on other sites

For the sake of completeness:
The wiki and the forum are a great source for good and efficient coding pactices :)


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2020-09-05 - Version 1.5.1.1) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2020-06-27 - Version 1.6.1.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX_GUI (NEW 2020-06-27 - Version 1.3.2.0) - Download
Outlook Tools (2019-07-22 - Version 0.6.0.0) - Download - General Help & Support - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
Task Scheduler (2019-12-03 - Version 1.5.1.0) - Download - General Help & Support - Wiki

Tutorials:
ADO - Wiki, WebDriver - Wiki

 

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

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Similar Content

    • By learner123
      Hi All,
       
      I am new to this AUTO IT and I have created a script that will open an app,enter pin and copy the code generated to clipboard. My java code call this autoIT script and use the copied generated code from clipboard.
      This works fine when server  window is on focus. My server is an windows server. 
      But when I minimize or disconnect the server, the script opens the app.exe but doesn't copy any value to clipboard.  
      Can anyone help me on this 😐
       
      Run("C:\Program Files (x86)\RSA SecurID Software Token\SecurID.exe")
      Local $hWnd=WinWait("abc - RSA SecurID Token") ; waits until the window is the active window
      $hWin = WinGetHandle("abc - RSA SecurID Token");
      ControlSend($hWnd,"","","1111") ; simulates pressing the Home key
      ControlSend($hWnd,"","","{ENTER}");
      ControlSend($hWnd,"","","^c");
      Sleep(1000) ;
      ControlSend($hWnd,"","","^c");
       
    • By learner123
      Hi All,
      So I have created a small autoIT script to enter pin into a RSA token(app which generate new code every 30 second), and copy the generated code.
      I have a java application which requires this code so every time my java-code requires this RSA code, it runs the autoIT script and the copied generated code is then used in my java application. 
      I have deployed this code on a windows server and it works fine when I am logged in and the window is on focus, But as soon as I schedule task and disconnect the server (not logged out only disconnect), or even minimize the server window, the autoIT scripts fails and its not able to copy the value.
       
      Please find below the code for AUTOIT.
       
      WinActivate("rsa - RSA SecurID Token") ; activates the window that has old in the tilte bar
      WinWaitActive("rsa - RSA SecurID Token") ; waits until the window is the active window
      Send("1111") ; simulates pressing the Home key, enters password to get the code
      Send("{ENTER}") ; simulates pressing the Enter key
      Sleep(1000) ;
      Send("^c") ; simulates pressing the CTRL+c keys (copy)
       
      Also I saw some post regarding that WINACTIVE only works when window is active. But my below AUTO IT script to handle windows pop up  works perfectly fine when the server is disconnected. 
       
      Opt("WinTitleMatchMode", 1)
      WinWait("https://url","","10")
      WinWaitActive("https://url","","10")
      Sleep(2000)
      Send("userid")
      Sleep(1000)
      Send("{TAB}")
      Sleep(1000)
      Send("passwrd")
      Send("{TAB}")
      Sleep(500)
      Send("{ENTER}")
       
       
    • By JuanFelipe
      Hello gyus, I try to make a code to login in a web page in my job, buy i can’t understand why my form is blocked, this is my code: 
      #include <ButtonConstants.au3> #include <EditConstants.au3> #include <GUIConstantsEx.au3> #include <StaticConstants.au3> #include <StringConstants.au3> #include <WindowsConstants.au3> #include <WinAPIFiles.au3> #include <FileConstants.au3> #include <File.au3> #include <Array.au3> #include <IE.au3> #include <Excel.au3> #include <GuiEdit.au3> #include <GuiStatusBar.au3> #include <DateTimeConstants.au3> #include <Date.au3> #Region ### START Koda GUI section ### Form=C:\noentry\koda_1.7.3.0\Forms\spoa.kxf $Form1 = GUICreate("Eva y Vehículos", 1200, 1000, 10, 10) $prueba = GUICtrlCreateButton("Prueba",10,990,50,20) ;VARIABLES ========================================================================================== $psi = "https://psi.policia.gov.co/PSI/Login.aspx?ReturnUrl=%2fPSI#no-back-button" $chequeVehiculos = "https://psi.policia.gov.co/PSI/frm_lista_chk.aspx" $evaluacionEva = "https://psi.policia.gov.co/PSI/eva_frmver.aspx" $oIE = ObjCreate("Shell.Explorer.2") $GUIActiveX = GUICtrlCreateObj ($oIE, 10, 10, 1180, 980) ;GUICtrlSetState(-1, $GUI_DISABLE) GUISetState(@SW_SHOW) $oIE.navigate($psi) ;_IELoadWait($oIE) _InicioSesion() #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $prueba _InicioSesion() EndSwitch WEnd Func _InicioSesion() Local $username = _IEGetObjByName($oIE, "txtUsuario") Local $pass = _IEGetObjByName($oIE, "txtClave") Local $logina = _IEGetObjByName($oIE, "btnIngresar") $username.value="example" $pass.value="examplepass" _IEAction($logina, 'click') _IELoadWait($oIE) MsgBox(16,"","") EndFunc  
    • By shelly
      Here is the below code for handling pop-up when window is  inactive ..but I don't know how to change sleep and when i run this script it runs sometimes and sometimes it stops .
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{SPACE}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{DOWN}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{ENTER}")
      --- these 3 lines never worked while TAB lines works sometimes but not in accurate way
      I am new too AutoIt .. help me out why this script behaves in strange way
      ControlFocus("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog", "", "Internet Explorer_Server1","1")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog", "", "Internet Explorer_Server1","the request is send")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{SPACE}")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{DOWN}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      Sleep(3000)
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{TAB}")
      ControlSend("Policy Decisions -- Webpage Dialog","","Internet Explorer_Server1","{ENTER}")
       
×
×
  • Create New...