aleph01 Posted September 24, 2014 Share Posted September 24, 2014 I know I can use Windows Task Scheduler, but I decided to write one in AutoIt. However, I am interested in gaining forum input as to whether my method is good, better, or best (or poor, worse, worst .) It works fine. I'm posing a challenge to others to write one that works just as well, but using different methods. Other methods will help me learn to be a better coder. Also, feel free to point out what I could have done better, if you don't want to write a scheduler. While 1 $MIN = @MIN $HOUR = @HOUR $WDAY = @WDAY If $WDay = 2 OR $WDay = 3 OR $WDay = 4 OR $WDay = 5 Or $WDay = 6 OR $WDAY = 7 Then ; Monday through Saturday If $HOUR = 18 Then ; at 6:00 pm If @Min = 00 Then ; on the hour (subject to my loop time) Run ("notepad.exe", "", @SW_MAXIMIZE) ; perform some activities WinWait ( "Untitled") Sleep (40001) WinClose ("Untitled") EndIf EndIf EndIf Sleep (40001) ; loop every 40 seconds so that 6:00 pm is always included, but only once a day WEnd Thanks in advance for making me better. Btw, the sleep 40001 I just picked up along the way. It sort of customizes my code to some extent, though I've seen it elsewhere. _aleph_ Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
JohnOne Posted September 24, 2014 Share Posted September 24, 2014 (edited) Here's a start. While 1 If @WDAY >= 2 And @HOUR = 18 And @MIN = 0 Then ; Monday through Saturday Run("notepad.exe", "", @SW_MAXIMIZE) ; perform some activities WinWait("Untitled") Sleep(40001) WinClose("Untitled") EndIf Sleep(40001) ; loop every 40 seconds WEnd Just shortened your code. Edited September 24, 2014 by JohnOne AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
aleph01 Posted September 24, 2014 Author Share Posted September 24, 2014 JohnOne, I appreciate your response, but I don't understand how If @WDAY >= 2 And @HOUR = 18 And @MIN = 0 Then ; Monday through Saturday works. Nevermind, I recall some C++. the >= does it. I will incorporate. Thanks for that! I'm a better coder already! Anybody else care to participate? I can really learn from, well pretty much everyone. I love this forum, and I often get a kick from forum rule-breaking posters who get "moderated". Please, anyone with more input, post! Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
JohnOne Posted September 24, 2014 Share Posted September 24, 2014 (edited) > greater than or = equal to Edited September 24, 2014 by JohnOne AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
JohnOne Posted September 24, 2014 Share Posted September 24, 2014 If this is a project you are going to expand and develop, and not just a one off, you should begin it as you mean to go on, and keep it modular. ; Keep your main loop easy to manage While 1 _Task1() _Task2() Sleep(40001) ; loop every 40 seconds WEnd Func _Task1() If @WDAY >= 2 And @HOUR = 18 And @MIN = 0 Then ; Monday through Saturday Run("notepad.exe", "", @SW_MAXIMIZE) ; perform some activities WinWait("Untitled") Sleep(40001) WinClose("Untitled") EndIf EndFunc ;==>_Task1 Func _Task2() ;code EndFunc AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
aleph01 Posted September 25, 2014 Author Share Posted September 25, 2014 JohnOne, thanks for the input, and WOW! the do it in functions is great! Thanks for the ideas. Seeing your expertise in coding, I doubt I'll ever be able to return the favor, but let me wish you every spiritual enhancement, just as you have given me coding enhancements beyond my expectations. _aleph_ btw, anyone who wants to contribute beyond, is very welcome to contribute. I'm trying to be a sponge. _aleph_ Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
Anteaus Posted September 25, 2014 Share Posted September 25, 2014 Aleph, your code looks OK except that your method of preventing repeats within the same minute might be unreliable. The right way to do this is to create am $armed flag for each event, and initalise it to false. In your main loop: IF the current time is equal to or later than the event time THEN ....IF $armed is true THEN .......fire the event .......reset $armed to false ....ENDIF ELSE ....set $armed to true ENDIF SLEEP a few seconds and repeat There is one special case, and that is an event scheduled for exactly midnight, which you may need to make allowance for. (There can be no time value less than 00:00) Though, not important if event is always at 18:00. This is basically how a mechanical timeswitch works - the peg on the dial compresses a spring as the set time approaches. At the set time the peg is disengaged, releasing the spring which trips the contacts smartly from one state to the other. Once the set time is past, the action cannot repeat until re-arming occurs. Also, you may find it easier to convert your times into 'hhmm' format and do a direct numeric comparison, rather than checking hour and minutes separately. HTH. Link to comment Share on other sites More sharing options...
javiwhite Posted September 25, 2014 Share Posted September 25, 2014 Hi Aleph. Are you looking to use the application on a longterm basis? If you are, I would suggest using a dynamic script, and avoid hardcoding any tasks into the actual scheduler itself... You could achieve this with an ini file, Which would contain all the data for tasks such as the frequency, Time, and directory of the program to execute. The benefit of this is that you can add additional tasks to your task scheduler without having to worry about editing the source code for the scheduler itself, It also means you could build a snazzy GUI for adding/removing tasks etc, as You wouldn't need to manually add them to the script! I've written a quick example to showcase what I mean: local $ini = @workingdir & "\config.ini" local $Tasks,$TaskInfo,$OldIni iniwrite($ini,"Test1","Dir","C:\temp\test1.exe") ;Create the ini for testing purposes iniwrite($ini,"Test1","Time","12:48") while 1 if FileRead($ini) <> $OldIni then ;Check for any updates to the ini file Console(FileRead($ini)) Console($OldIni) $Tasks = IniReadSectionNames($ini) ;Gathers each section name from ini (the identifier used per task in this example) $OldIni = FileRead($ini) ;Stores Entire contents of Ini to variable (Cheap and ugly update check on the config) if IsArray($TaskInfo) then ;Avoid ReDim Errors by checking if array exists before declaration ReDim $TaskInfo[Ubound($Tasks)][4] Else Dim $TaskInfo[Ubound($Tasks)][4] EndIf For $i = 0 to uBound($Tasks) - 1 ; For Loop to gather all task data for each task into an array $TaskInfo[$i][0] = $Tasks[$i] $TaskInfo[$i][1] = iniRead($ini,$Tasks[$i],"Dir","") $TaskInfo[$i][2] = iniRead($ini,$Tasks[$i],"Time","") $TaskInfo[$i][3] = False ;Flag to ensure only run once Next EndIf For $x = 0 to Ubound($TaskInfo,1) - 1 ;For loop to check if any tasks are to be run. if @HOUR & ":" & @MIN = $TaskInfo[$x][2] and $TaskInfo[$x][3] == False Then Run($TaskInfo[$x][1]) ; Run the task using the Directory value stored in the config file $TaskInfo[$x][3] = True ; Set the run flag to true for this task EndIf Next WEnd This application, albeit very basic, will run any files mentioned in the config.ini. If you haven't tried using the native ini functions, I would really suggest playing with them, as they're really easy to use... I certainly haven't looked back. Just a suggestion - Javi dynamitemedia 1 give a man an application, and he'll be frustrated for the day, Teach him how to program applications and he'll be frustrated for a lifetime. Link to comment Share on other sites More sharing options...
aleph01 Posted September 28, 2014 Author Share Posted September 28, 2014 Great! It looks like I have lots of "directed learning" to do. JohnOne, thanks for the suggestions - you'll see many of them incorporated in the code I'm posting. However, I am running into trouble with the conditional operator, though the If/Then/EndIf structure works. More on that in a moment. Anteaus, I see what you mean. That'll probably be the next thing I'll incorporate, once I get straightened out on the conditional operator. Javiwhite, I can see the advantages you pointed out about .ini files. Writing one will be a first for me and feels over my head, but how will I ever learn if I don't take on more challenging things? Having the code run the timer and pulling the tasks from an .ini is on my list too. Here's my current problem. Going from an If/Then/EndIf structure to the conditional operator gives me one of two messages. Either I get "Error in expression" if I don't use brackets, or I get an error stating that I need an ending bracket, although there appears to be no case in which I haven't closed an opening bracket. I've renamed Tasks 1 & 2 to something more descriptive and am trying to get this running with the Scheduler module totally separate from the Tasks module. That should help when it's .ini time. This script should stay in the scheduler loop most of the time, move on to the Tasks function and then loop back to the Scheduler function. Here's the code: While 1 _Scheduler() _Tasks() WEnd Func _Scheduler() While 1 (@WDAY >= 1 And @HOUR = 10 And @MIN = 50) ? (ExitLoop) : (Sleep (40001)) WEnd EndFunc ;==>_Scheduler Func _Tasks() Run("notepad.exe", "", @SW_MAXIMIZE) ; perform some tasks WinWait("Untitled") Sleep(40001) WinClose("Untitled") EndFunc ;==>_Tasks It's the line in the scheduler function that gives the error. It appears to do fine when it's sleeping and waiting for the condition to be true. When the condition is true, I get the errors below - couldn't seem to copy and paste it here. (@WDAY >= 1 And @HOUR = 11 And @MIN = 31 ? (ExitLoop): (Sleep (40001)) ^ERROR Error: Missing right bracket ')' in expression. OR Error In Expression (located in the same place.) Thanks, for the help. _aleph_ Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
JohnOne Posted September 28, 2014 Share Posted September 28, 2014 I do not believe you can have a keyword (ExitLoop) in ternary condition like that. AutoIt Absolute Beginners Require a serial Pause Script Video Tutorials by Morthawt ipify Monkey's are, like, natures humans. Link to comment Share on other sites More sharing options...
aleph01 Posted September 28, 2014 Author Share Posted September 28, 2014 Well, isn't that a disappointment! Well, the If/Then/EndIf works, so I'm using the code below for the Scheduler function. The Tasks function works like a charm. Now to address the timing issue and then incorporating an .ini file... I'll be back... Thanks all! _aleph_ Func _Scheduler() While 1 If @WDAY >= 1 AND @HOUR = 16 AND @MIN = 30 Then ExitLoop Else Sleep (60001) EndIf WEnd EndFunc ;==>_Scheduler Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
aleph01 Posted September 28, 2014 Author Share Posted September 28, 2014 javiwhite, I realize I never answered your first question. I'm not expecting to use this as anything other than a learning tool. I have a problem with going through tutorials as dogma. I never want to write another "Hello world" again. I require a purpose to write code. A school assignment qualifies, but alas, I'm not in school at this time, and when I was, I studied Biology and Chemistry (along with Philosophy and Math). Having said that, I can't say why I chose this as a project, since Windows has this native ability, but if I can be motivated by this project, it suits my needs as far as learning, and AutoIt and this forum provide the means, since I really like AutoIt. Thanks, Jon! ..and the contributing crew! _aleph_ Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
aleph01 Posted October 1, 2014 Author Share Posted October 1, 2014 Anteaus, if you're still watching this thread, here's what me Scheduler function code looks like after incorporating your $armed variable suggestion. Correct me if I don't appear to be using it right. Func _Scheduler() $armed = false While 1 If @WDAY >= 1 AND @HOUR = 16 AND @MIN = 30 Then If $armed = true Then ExitLoop Else $armed = true Sleep (40001) EndIf WEnd EndFunc ;==>_Scheduler While looking at it and trying to figure out the flow of commands, I realized that I didn't need to reset $armed to false before ExitLoop because ExitLoop throws me out of the Scheduler function as well, and when the main script loops me back to the Scheduler function, $armed is set to false first thing. Let me know if I'm not using the $armed flag correctly. It looks like my Tasks function will need to have a >1 minute sleep time to assure that I don't return to the Scheduler task too soon after running Tasks. This weekend, it will be looking at how to use .ini files for the Tasks function. Thanks all! _aleph_ Meds. They're not just for breakfast anymore. Link to comment Share on other sites More sharing options...
dynamitemedia Posted June 18, 2015 Share Posted June 18, 2015 (edited) Hi Aleph.Are you looking to use the application on a longterm basis? If you are, I would suggest using a dynamic script, and avoid hardcoding any tasks into the actual scheduler itself...You could achieve this with an ini file, Which would contain all the data for tasks such as the frequency, Time, and directory of the program to execute.The benefit of this is that you can add additional tasks to your task scheduler without having to worry about editing the source code for the scheduler itself, It also means you could build a snazzy GUI for adding/removing tasks etc, as You wouldn't need to manually add them to the script!I've written a quick example to showcase what I mean:local $ini = @workingdir & "\config.ini" local $Tasks,$TaskInfo,$OldIni iniwrite($ini,"Test1","Dir","C:\temp\test1.exe") ;Create the ini for testing purposes iniwrite($ini,"Test1","Time","12:48") while 1 if FileRead($ini) <> $OldIni then ;Check for any updates to the ini file Console(FileRead($ini)) Console($OldIni) $Tasks = IniReadSectionNames($ini) ;Gathers each section name from ini (the identifier used per task in this example) $OldIni = FileRead($ini) ;Stores Entire contents of Ini to variable (Cheap and ugly update check on the config) if IsArray($TaskInfo) then ;Avoid ReDim Errors by checking if array exists before declaration ReDim $TaskInfo[Ubound($Tasks)][4] Else Dim $TaskInfo[Ubound($Tasks)][4] EndIf For $i = 0 to uBound($Tasks) - 1 ; For Loop to gather all task data for each task into an array $TaskInfo[$i][0] = $Tasks[$i] $TaskInfo[$i][1] = iniRead($ini,$Tasks[$i],"Dir","") $TaskInfo[$i][2] = iniRead($ini,$Tasks[$i],"Time","") $TaskInfo[$i][3] = False ;Flag to ensure only run once Next EndIf For $x = 0 to Ubound($TaskInfo,1) - 1 ;For loop to check if any tasks are to be run. if @HOUR & ":" & @MIN = $TaskInfo[$x][2] and $TaskInfo[$x][3] == False Then Run($TaskInfo[$x][1]) ; Run the task using the Directory value stored in the config file $TaskInfo[$x][3] = True ; Set the run flag to true for this task EndIf Next WEndThis application, albeit very basic, will run any files mentioned in the config.ini. If you haven't tried using the native ini functions, I would really suggest playing with them, as they're really easy to use... I certainly haven't looked back. Just a suggestion - JaviThis works great BUT anytime something new is added to the INI file it restarts the program from the INI resetting the flags to false is what you mentioned via PM For $x = 0 to Ubound($TaskInfo,1) - 1 ;For loop to check if any tasks are to be run. if @HOUR & ":" & @MIN = $TaskInfo[$x][2] and $TaskInfo[$x][3] == False Then Run($TaskInfo[$x][1]) ; Run the task using the Directory value stored in the config file $TaskInfo[$x][3] = True ; Set the run flag to true for this task EndIf Next WEnd Edited June 18, 2015 by dynamitemedia f Link to comment Share on other sites More sharing options...
javiwhite Posted June 19, 2015 Share Posted June 19, 2015 Hey Dynamite,Indeed, as mentioned over PM, the array is rebuilt every time the config file is updated, A way around this is to reserve the old information, until the task array is fully rebuilt (after which the old information should be discardedI've updated the snippet, Try this out and see how you get on.I've commented what's occurring, and left in the array checks, So you can work back through the changes, and learn how to resolve the issue.expandcollapse popup#include<Array.au3> local $ini = @workingdir & "\config.ini" local $Tasks,$TaskInfo,$OldIni,$OldTaskInfo iniwrite($ini,"Test1","Dir","C:\temp\test1.exe") ;Create the ini for testing purposes iniwrite($ini,"Test1","Time","09:17") while 1 sleep(10) if FileRead($ini) <> $OldIni then ;Check for any updates to the ini file ConsoleWrite(FileRead($ini) & @CR) ConsoleWrite($OldIni & @CR) $Tasks = IniReadSectionNames($ini) ;Gathers each section name from ini (the identifier used per task in this example) $OldIni = FileRead($ini) ;Stores Entire contents of Ini to variable (Cheap and ugly update check on the config) if IsArray($TaskInfo) then ;Avoid ReDim Errors by checking if array exists before declaration $OldTaskInfo = $TaskInfo ;temporarily store old information ReDim $TaskInfo[Ubound($Tasks)][4] Else Dim $TaskInfo[Ubound($Tasks)][4] EndIf For $i = 1 to uBound($Tasks) - 1 ; For Loop to gather all task data for each task into an array $TaskInfo[$i][0] = $Tasks[$i] $TaskInfo[$i][1] = iniRead($ini,$Tasks[$i],"Dir","") $TaskInfo[$i][2] = iniRead($ini,$Tasks[$i],"Time","") $TaskInfo[$i][3] = False ;Set the default state (Hasn't run) for $x = 1 to uBound($OldTaskInfo,1) - 1 ;Cycle through old task array if $OldTaskInfo[$x][0] = $TaskInfo[$i][0] Then ;If one of our tasks is from previous task array $TaskInfo[$i][3] = $OldTaskInfo[$x][3] ;Gather the flag setting from the old array and replace default state ExitLoop ;No need to cycle through further tasks, We've found the one we're looking for. EndIf Next Next $OldTaskInfo = '' ;Clear the variable containing outdated info _ArrayDisplay($TaskInfo) ;display results EndIf For $x = 0 to Ubound($TaskInfo,1) - 1 ;For loop to check if any tasks are to be run. if @HOUR & ":" & @MIN = $TaskInfo[$x][2] and $TaskInfo[$x][3] == False Then Run($TaskInfo[$x][1]) ; Run the task using the Directory value stored in the config file $TaskInfo[$x][3] = True ; Set the run flag to true for this task _ArrayDisplay($TaskInfo) EndIf Next WEnd Hope it helpsJavi give a man an application, and he'll be frustrated for the day, Teach him how to program applications and he'll be frustrated for a lifetime. Link to comment Share on other sites More sharing options...
dynamitemedia Posted June 19, 2015 Share Posted June 19, 2015 (edited) Ok been making adjustments to fit what i have, but this is NOT displaying in console or array display when a new item is put in INI is that normal? EDIT: just using as is does not show the updates in the consoleEDIT: it was cause the split of this line;Gather the flag setting from the old array and replace default stateThanks seems to be working thus far will come back and update when i play with it some more! Edited June 20, 2015 by dynamitemedia 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