devilspride Posted August 1, 2020 Share Posted August 1, 2020 Q. HOW TO DEFINE A COMMON SET OF VARIABLES AND FUNCTIONS FOR MULTIPLE SCRIPTS ? I have been coding AutoIt for almost an year now. This is my first post in forum, i will be as specific as possible. Here is my project and the issues I am facing (alongside with steps i have tried to resolve them but couldn't, due to reasons stated) AIM OF MY PROJECT: To manage my daily tasks Design : I have a Master Script (Controller.au3) which contains a GUI to determine which TASK to execute based on various factors. Each TASK has a separate Script which is executed or terminated via the Controller.au3 GUI. Picture 1.1 - ProjectOutline Under each TASK Script, there are basically 3 Regions #Region SCRIPT REGION : contains the TASK code #Region COMMON INITIAL VARIABLES : contains few variables that all of my TASK(s) will require. They are basically stored INI values which are master controlled by Controller.au3 GUI (code attached} #Region ;;COMMON INITIAL VARIABLES ;;;AUTOIT OPTIONS #NoTrayIcon Opt("PixelCoordMode", 0) ;1=absolute, 0=relative, 2=client ;;;INI VARS Global $ScriptName = StringTrimRight(@ScriptName, 4) ;parent directories Global $Dir_Task=StringTrimRight(@ScriptDir,StringLen('\scripts\' & $ScriptName)) Global $Dir_config = $Dir_Task & '\config' ;parent INIs Global $settingsINI=$Dir_config & '\settings.ini' Global $operational=$Dir_config & '\operational.ini' Global $Dir_Root = StringTrimRight($Dir_Task,StringLen(IniRead($settingsINI,'ActiveWindow','WindowTitle',0)) Global $Dir_assets = $Dir_Root & '\assets' Global $Dir_DLL = $Dir_Root & '\DLLs' ;;; WINDOW VARIABLES Global $WinTitle=IniRead($settingsINI,'Emulator','WindowTitle','error') Global $WinHandle = WinGetHandle($WinTitle,'') If @error Then ;WinHandle error handler ER('WinHandle does not exist',2) _EndProgram('WinHandle not found') Else Global $WinPos = WinGetPos($WinHandle) EndIf Global $Win_Static_X=IniRead($settingsINI,'Window','StaticX',640) Global $Win_Static_Y=IniRead($settingsINI,'Window','StaticX',369) WinMove($WinHandle,'',$WinPos[0],$WinPos[1],$Win_Static_X, $Win_Static_Y) ;;; TIMER VARS Global $LastRuntime=IniRead($settingsINI,$ScriptName,'LastRuntime',0) Global $TimeGap=IniRead($settingsINI,$ScriptName,'TimeGap',0) ;;; MISC VARS Global $RequestCounter = IniRead($settingsINI,$ScriptName,'RequestCounter','0') ;;; ACCOUNT VARS Global $username = IniRead($settingsINI,'Account','Username',0) ;;; IMAGE-DEBUG VARS Global $xcoord = 0 Global $ycoord = 0 Global $ImageDebugMode = IniRead($settingsINI,$ScriptName, 'ImageDebugMode', 0) Global $ImageDebugger ;;; LOGGING Global $LogPath = @ScriptDir & '\' & $ScriptName & '.log' FileDelete($LogPath) Global $MainErrorLog = $Dir_Bot & '\Logs\Errors.log' Global $ImageLog = IniRead($settingsINI,$ScriptName,'ImageLog',1) Global $ChatAnnounce = IniRead($settingsINI,$ScriptName,'ChatAnnounce',1) #EndRegion #Region COMMON UDFs : Contains a lot of functions that are again going to be used by all of my TASK scripts during their execution. {example code attached of a very simple function} Func ER($msg,$code) $year = @YEAR $month = @MON $date = @MDAY $hour = @HOUR $minute = @MIN $minute = @SEC FileWrite($MainErrorLog,$year & '-' & $month & '-' & $date & @TAB & $hour & '-' & $minute & '-' & $minute & @TAB & 'Error (' & $code & ')' & @TAB & '{' & $ScriptName & '}' & @TAB & $msg & @CRLF) Switch $code Case 1 ;MINOR ERROR - LOG WRITE CR('!Error : ' & $msg) Case 2 ;MAJOR ERROR - LOG WRITE + TOOLTIP ToolTip($msg,$WinPos[0] -20 + ($WinPos[2])/2 ,$WinPos[1] -20 + ($WinPos[3])/2 ,$username & '-' & $ScriptName,2) CR('!Error : ' & $msg) Sleep(5000) ToolTip('') EndSwitch ;;PRINT ERROR WINDOW PrintScreen('Logs\ImageLogs\Errors\' & $year & '-' & $month & '-' & $date,$hour& '-' & $minute & '-' & $minute & ' ' & $msg) EndFunc So the workflow is Controller.au3 >> (starts a script and writes INI) >> Common Variables Loaded from INI >> Script Running PROBLEM FACED: How to pass the common variables to each script ? I want to declare those list of variables for each and every script that runs. Currently i am copy and pasting the entire region in all the scripts. But the issue comes, when i have to make some changes to any variable in #Region COMMON INITIAL VARIABLES or any function in #Region COMMON UDF , then i have to copy and paste those regions in all the scripts (which can go upto 30+ scripts in future) I need a better way to define those common variables and functions for all the scripts. TRIED METHODS - FAILED I have tried the following methods but failed to achieve anything more productive then copy pasting the regions. Declaring those variables from the Controller.au3 : if i declare them from Controller.au3 then i have to pass them via ShellExecute or as parameters of a Function Call, which is quiet tedious in my case as Common Variable are more than 30+. {I have reduced 50% of the variables to avoid the bloat in the above example code} Adding all the scripts to the Controller.au3 : Makes the GUI unresponsive because of many internal loops in each TASK which waits for user input or waits for process completion. Tried using Loop interruptions : (as mentioned in Wiki) , works fine for a few scripts, but for 30-50+ TASKS, become cumbersome. From Forums : Tried MailSlot, but the idea remains same, i have to checkmailslotmessage in every script again to define and use the variables there. BACKUP If everything fails, then i will make a script to read all the TASK scripts and identify a particular marker "Keywork" for starting of each region and then From Line A to Line B, delete everything and insert a new code. Repeat this in a loop for all the TASK scripts. Then Batch-Complile them all. But this is a very crude method. I am reserving it for the last attempt. Link to comment Share on other sites More sharing options...
jchd Posted August 1, 2020 Share Posted August 1, 2020 Make only one big .exe 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 hereRegExp tutorial: enough to get startedPCRE 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) Link to comment Share on other sites More sharing options...
Gianni Posted August 1, 2020 Share Posted August 1, 2020 I don't know if I understand exactly the need, however it is worth taking a look at this interesting post by @LarsJ (https://www.autoitscript.com/forum/topic/202618-implementing-irunningobjecttable-interface) which can probably be useful for your purpose. For example, you can declare a single array and use the individual elements of the array instead of many different variables. This array (and its content) can therefore be shared among all the different scripts that can read and/or modify its content independently. This way changes made by one script can be read by another script. Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
orbs Posted August 1, 2020 Share Posted August 1, 2020 @devilspride, welcome to the AutoIt forum. notice that when you #include some external file, that file which you create yourself (often known as UDF) does not have to include functions only - it can include whatever code you choose, be it variables or constants declarations, option statements, function calls, etc. so you can put all the region of the COMMON INITIAL VARIABLES into a dedicated file, and #include it in all your scripts. or am i missing something? devilspride 1 Signature - my forum contributions: Spoiler UDF: LFN - support for long file names (over 260 characters) InputImpose - impose valid characters in an input control TimeConvert - convert UTC to/from local time and/or reformat the string representation AMF - accept multiple files from Windows Explorer context menu DateDuration - literal description of the difference between given dates Apps: Touch - set the "modified" timestamp of a file to current time Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes SPDiff - Single-Pane Text Diff Link to comment Share on other sites More sharing options...
devilspride Posted August 1, 2020 Author Share Posted August 1, 2020 14 hours ago, jchd said: big .exe XD will do that if no option left. 8 hours ago, Chimp said: I don't know if I understand exactly the need, however it is worth taking a look at this interesting post by @LarsJ (https://www.autoitscript.com/forum/topic/202618-implementing-irunningobjecttable-interface) which can probably be useful for your purpose. For example, you can declare a single array and use the individual elements of the array instead of many different variables. This array (and its content) can therefore be shared among all the different scripts that can read and/or modify its content independently. This way changes made by one script can be read by another script. I will give this is a go. But there is high chance it will have the same issues, because i am calling some variables and then i have to again recall those variables in the child scripts, just the method is different. What i want is a solution that i dont want to edit my child scripts again and again to add the common variables or functions. Using ROT i am basically calling their handles rather than declaring them explicitly. 1 hour ago, orbs said: @devilspride, welcome to the AutoIt forum. notice that when you #include some external file, that file which you create yourself (often known as UDF) does not have to include functions only - it can include whatever code you choose, be it variables or constants declarations, option statements, function calls, etc. so you can put all the region of the COMMON INITIAL VARIABLES into a dedicated file, and #include it in all your scripts. or am i missing something? Exactly thats what i thought when i started the project. But it gives the error that the variables are undeclared. i will write and example and post it. Maybe i missed something there. That would be the easiest thing if i can do that. Then i will just have to place one au3 file in the root directory and everything is fine. Link to comment Share on other sites More sharing options...
TheXman Posted August 1, 2020 Share Posted August 1, 2020 (edited) 16 hours ago, devilspride said: PROBLEM FACED: How to pass the common variables to each script ? I want to declare those list of variables for each and every script that runs. Currently i am copy and pasting the entire region in all the scripts. But the issue comes, when i have to make some changes to any variable in #Region COMMON INITIAL VARIABLES or any function in #Region COMMON UDF , then i have to copy and paste those regions in all the scripts (which can go upto 30+ scripts in future) I need a better way to define those common variables and functions for all the scripts. It sounds like you need data that can be accessed by any of your task-related scripts. You also need to be able to easily make changes to that data and for those task-related scripts to be able to pick up those changes without a huge amount of maintenance to each script. What you are describing sounds like a central repository for data/settings/configuration information, in other words a database. The database could be a flat file like an INI file, or a relational database like SQLite. So the scripts just query the database for the common information. Am I missing something in your requirements? 🤔 Of course I'm talking about the data not the functions. Edit: I see that your issue was with how to properly include .au3 files into your scripts. I guess you can disregard my post. However, if you are compiling your scripts to executable files, using includes will require you to recompile if changes are made to them. Edited August 1, 2020 by TheXman CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
devilspride Posted August 1, 2020 Author Share Posted August 1, 2020 Thanks to @orbs I made a test script to include all my COMMON VARIABLES and COMMON FUNCTIONS in the root and it worked with my TEST scripts. But i get it now why i was having problems. Maybe i am wrong but i think it was due to a extra "." in the help file that was throwing errors. This works : #include "..\includes\common.au3" But this doesn't : #include "...\includes\common.au3" The helpfile tells us to use the latter one. Maybe i missed something in how to use the helpfile for #include P.S. : it was actually my typo that i used ".." instead of "..." 😆😆 Link to comment Share on other sites More sharing options...
devilspride Posted August 1, 2020 Author Share Posted August 1, 2020 3 minutes ago, TheXman said: It sounds like you need data that can be accessed by any of your task-related scripts. You also need to be able to easily make changes to that data and for those task-related scripts to be able to pick up those changes without a huge amount of maintenance to each script. What you are describing sounds like a central repository for data/settings/configuration information, in other words a database. The database could be a flat file like an INI file, or a relational database like SQLite. So the scripts just query the database for the common information. Am I missing something in your requirements? 🤔 Yes @TheXman absolutely correct. For the most parts i was using the INIs as my central repository. The only issue was the polling and requesting data from each task script required the variables and functions to be declared inside them. which i was trying to reduce by a better way. Finally got the answer. Thank you everyone for a quick solution to my issue. *P.S. Is the helpfile information on relative paths for #include correct ? Because i was using that format in my previous attempts to solve my issues, but got errors of "path not found" and "variables not declared" if i used the AutoIt helpfile format. Luckily / unluckily i was sleepy and just used two ".." instead of three "..." and it worked like charm. Link to comment Share on other sites More sharing options...
TheXman Posted August 1, 2020 Share Posted August 1, 2020 6 minutes ago, devilspride said: *P.S. Is the helpfile information on relative paths for #include correct ? Yes CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
devilspride Posted August 1, 2020 Author Share Posted August 1, 2020 Haven't searched the forums for it but during my testing found an interesting thing. Maybe helpful for others who are using Relative paths for #includes Example 1 - common file is in same folder Script Path : W:\AutoIt\Testing\main\main.au3 Include Path : W:\AutoIt\Testing\main\common.au3 To include common.au3 in main.au3 use the following code #include "common.au3" Example 2 - common file is in Sub-Folder Script Path : W:\AutoIt\Testing\main\main.au3 Include Path : W:\AutoIt\Testing\main\includes\common.au3 #include ".\includes\common.au3" Here "." represents one level up of directory . = Path to "main" directory Example 3 - common file is in parent folder Script Path : W:\AutoIt\Testing\main\main.au3 Include Path : W:\AutoIt\Testing\includes\common.au3 #include "..\includes\common.au3" ".." represents two level up i.e. Path to "Testing" directory ** Unfortunately "..." does not work if i want to place an #include file in directory 3 levels up i.e. in "AutoIt" folder. This is just for reference for others if they stumble upon the same topic. I do not mean to start another discussion / thread. I have already got the answer. Thank you all for the support and other ideas. Link to comment Share on other sites More sharing options...
TheXman Posted August 1, 2020 Share Posted August 1, 2020 (edited) 2 levels up would be "..\..\includes\common.au3", 3 levels "..\..\..\Includes\common.au3" and so on. In DOS/CMD, there is no such syntax as "...\" .\ = current directory ..\ = parent directory so ..\..\ = parent of parent directory "..." as it relates to the help file for the INCLUDE directive, is an ellipsis meaning "whatever is necessary to complete this part" goes here. 😄 Edited August 1, 2020 by TheXman CryptoNG UDF: Cryptography API: Next Gen jq UDF: Powerful and Flexible JSON Processor | jqPlayground: An Interactive JSON Processor Xml2Json UDF: Transform XML to JSON | HttpApi UDF: HTTP Server API | Roku Remote: Example Script About Me How To Ask Good Questions On Technical And Scientific Forums (Detailed) | How to Ask Good Technical Questions (Brief) "Any fool can know. The point is to understand." -Albert Einstein "If you think you're a big fish, it's probably because you only swim in small ponds." ~TheXman Link to comment Share on other sites More sharing options...
devilspride Posted August 2, 2020 Author Share Posted August 2, 2020 4 hours ago, TheXman said: 2 levels up would be "..\..\includes\common.au3", 3 levels "..\..\..\Includes\common.au3" and so on. In DOS/CMD, there is no such syntax as "...\" .\ = current directory ..\ = parent directory so ..\..\ = parent of parent directory "..." as it relates to the help file for the INCLUDE directive, is an ellipsis meaning "whatever is necessary to complete this part" goes here. 😄 Thank you for the reply Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now