AHK Scheduler is some sort of Window's Scheduled Tasks clone, completely written in AHK. The scheduler
- Survives a restart
- Can be uses with accounts without password (unlike Windows Scheduled Tasks)
- Can optionally wake the computer up from standby mode to execute a task
- It's possible to schedule more than one task
.
The scripts are testet on XPHome SP1 and XP Pro SP2. It should work on Windows98, Windows 2000 too. It's tested with AHK 1.0.44.7, but it should work with v1.0.36.07+. Wake up from Hibernate requires hardware support for S4-mode. You can find more info about standby-modes
here
AHK-scheduler consists of to scripts. Both scripts must be in the same directory:
1. The GUI Script
The GUI script sets the timer and starts the timer script.
Code:
WakeUpMain=WakeUp.ahk
;GUI
Gui, Add, GroupBox, x10 y8 w150 h126, Application:
Gui, Add, Text, xp+6 y27 w60 h20, StartDate:
Gui, Add, Text, xp y57 wp hp , StartTime:
Gui, Add, DateTime, x70 y27 wp20 h20 vStartDate Section,
Gui, Add, DateTime, xp y57 wp hp vStartTime 1, HH:mm:00 ;time
Gui, Add, Text, x16 y84 w80 h20 , Run (with path):
Gui, Add, ComboBox, xp yp+16 w134 choose1 vStart, sol.exe|notepad.exe|cmd.exe
Gui, Add, GroupBox, x10 y140 w150 h60 , Wake up from Standby?
Gui, Add, Radio, xp+25 yp+25 vWakeUp, &No
Gui, Add, Radio, xp+55 yp Checked, &Yes
Gui, Add, GroupBox, x170 y8 w150 h126, Power Management
Gui, Add, Radio, xp+36 y27 w80 h26 Checked, &Keep running
Gui, Add, Radio, xp y+10 wp hp vStandby, &Hibernate NOW
Gui, Add, Radio, xp y+10 wp hp , &Suspend NOW
Gui, Add, Button, x170 y160 w48, &Help
Gui, Add, Button, xp+50 yp wp, &Cancel
Gui, Add, Button, xp+50 yp wp Default, &OK
Gui, Show,, AHK-Scheduler
Return
; SUBROUTINES
ButtonOK:
Gui, submit, nohide
; Format date and time for wake-up-function
Stringmid, YYYY,StartDate,1,4 ;Year
Stringmid, MM,StartDate,5,2 ;Month
Stringmid, DD,StartDate,7,2 ;Day
Stringmid, Hour,StartTime,9,2 ;hour
Stringmid, Min,StartTime,11,2 ;minute
;Add "" to application name
Start="%Start%"
; Prepare code for standby-type: 0=no standby 1= hibernate 2= suspend (Radio Buttons in a group are numbered!)
Standby:=Standby-1
; Prepare code for wake-up: 0=no wake up 1= wake up
Resume:=WakeUp-1
; Set Timer by running timer script
run, autohotkey.exe %WakeUpMain% %YYYY% %MM% %DD% %Hour% %Min% %Standby% %Start% %Resume%
return
Esc::
ButtonCancel/Exit:
GuiClose:
ExitApp
ButtonHelp:
MsgBox, Help file is under construction.
return
2. The Timer ScriptCode:
/*
Writes a timer script to Startup-directory. The Wake-Up-Timer script deletes itself when the timer is finished
Hibernates the computer, depending on variable "Hibernate"
*/
; *************
; CONFIGURATION
; *************
YYYY=%1% ;Parameter 1: Year
MM=%2% ;Parameter 2: Month
DD=%3% ;Parameter 3: Day
Hour=%4% ;Parameter 4: hour
Min=%5% ;Parameter 5: minute
Hibernate=%6% ;Parameter 6: Hibernate, suspend, keep running?
Start=%7% ;Parameter 7: Application to run
Resume=%8% ;Parameter 8; Resume to run application? Yes/No
ScheduledTime=%YYYY%%MM%%DD%%Hour%%Min%%A_sec%
; ***********
; AUTOEXECUTE
; ***********
;Get name of application to be started from it's path:
SplitPath, Start, FileName
StringReplace, FileName,FileName,", ;Remove "
;Writes the timer script to Startup-directory
WriteAutostartFile(YYYY,MM,DD,Hour,Min,Start,Resume,FileName)
;Starts the timer from Startup-directory
Run, %A_startup%\%ScheduledTime%_%Filename%.ahk
;Hibernates the computer, depending on variable "Hibernate":
If Hibernate=1 ;Hibernate
{
DllCall("PowrProf\SetSuspendState", "int", 1, "int", 0, "int", 0)
}
If Hibernate=2 ;Suspend
{
DllCall("PowrProf\SetSuspendState", "int", 0, "int", 0, "int", 0)
}
; *********
; FUNCTIONS
; *********
WriteAutostartFile(YYYY,MM,DD,Hour,Min,Start,Resume,FileName)
; Writes Wake-Up-Timer script to Startup directory . After a restart the script will run again and set the timer.
; The Wake-Up-Timer script deletes itself when the timer is finished or when duetime is over at startup
{
ScheduledTime=%YYYY%%MM%%DD%%Hour%%Min%%A_sec%
FileAppend,
(
YYYY=%YYYY%
MM=%MM%
DD=%DD%
Hour=%Hour%
Min=%Min%
Start=%Start% ; Application to run
Resume=%Resume% ; Resume to run application? Yes/No
ScheduledTime=%YYYY%%MM%%DD%%Hour%%Min%%A_sec%
Name=%A_Now% ;Name of the Timer Object
If (A_Now>ScheduledTime)
{
;x := (A_Now-%ScheduledTime%)
; msgbox, `%A_Now`%`(A_Now)``n%ScheduledTime% (scheduledTime)``n`%x`%
; exitApp
msgbox, The application ``n %FileName% ``ncould not be started as scheduled``n %YYYY%-%MM%-%DD% %Hour%:%Min%
FileDelete, %A_startup%\%ScheduledTime%_%Filename%.ahk
exitApp
}
else
{
Menu, tray, tip, Wake-Up-Timer``nStart Time: %YYYY%-%MM%-%DD% %Hour%:%Min%``nApplication: %FileName%
WakeUp(YYYY, MM, DD, Hour, Min, Resume, Name)
run, %Start%
FileDelete, %A_startup%\%ScheduledTime%_%Filename%.ahk
return
}
; FUNCTIONS
WakeUp(Year, Month, Day, Hour, Minute, Resume, Name)
;Awaits duetime, then returns to the caller (like some sort of "sleep until duetime").
;If the computer is in hibernate or suspend mode
;at duetime, it will be reactivated (hardware support provided)
;Parameters: Year, Month, Day, Hour, Minute together produce duetime
;Resume: If Resume=1, the system is restored from power save mode at due time
;Name: Arbitrary name for the timer
{
duetime:=GetUTCFileTime(Year, Month, Day, Hour, Minute)
Handle:=DLLCall("CreateWaitableTimer"
,"char *", 0
,"Int",0
,"Str",name, "UInt")
DLLCall("CancelWaitableTimer","UInt",handle)
DLLCall("SetWaitableTimer"
,"Uint", handle
,"Int64*", duetime ;duetime must be in UTC-file-time format!
,"Int", 1000
,"uint",0
,"uint",0
,"int",resume)
Signal:=DLLCall("WaitForSingleObject"
,"Uint", handle
,"Uint",-1)
DllCall("CloseHandle", uint, Handle) ;Closes the handle
}
GetUTCFiletime(Year, Month, Day, Hour, Min)
;Converts "System Time" (readable time format) to "UTC File Time" (number of 100-nanosecond intervals since January 1, 1601 in Coordinated Universal Time UTC)
{
DayOfWeek=0
Second=00
Millisecond=00
;Converts System Time to Local File Time:
VarSetCapacity(MyFiletime , 64, 0)
VarSetCapacity(MySystemtime, 32, 0)
InsertInteger(Year, MySystemtime,0)
InsertInteger(Month, MySystemtime,2)
InsertInteger(DayOfWeek, MySystemtime,4)
InsertInteger(Day, MySystemtime,6)
InsertInteger(Hour, MySystemtime,8)
InsertInteger(Min, MySystemtime,10)
InsertInteger(Second, MySystemtime,12)
InsertInteger(Millisecond,MySystemtime,14)
DllCall("SystemTimeToFileTime", Str, MySystemtime, UInt, &MyFiletime)
LocalFiletime := ExtractInteger(MyFiletime, 0, false, 8)
;Converts local file time to a file time based on the Coordinated Universal Time (UTC):
VarSetCapacity(MyUTCFiletime , 64, 0)
DllCall("LocalFileTimeToFileTime", Str, MyFiletime, UInt, &MyUTCFiletime)
UTCFiletime := ExtractInteger(MyUTCFiletime, 0, false, 8)
Return UTCFileTime
}
ExtractInteger(ByRef pSource, pOffset = 0, pIsSigned = false, pSize = 32)
; Documented in Autohotkey Help
{
Loop `%pSize`%
result += *(&pSource + pOffset + A_Index-1) << 8*(A_Index-1)
if (!pIsSigned OR pSize > 4 OR result < 0x80000000)
return result
return -(0xFFFFFFFF - result + 1)
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4)
; Documentated in Autohotkey Help
{
Loop `%pSize`%
DllCall("RtlFillMemory", UInt, &pDest + pOffset + A_Index-1
, UInt, 1, UChar, pInteger >> 8*(A_Index-1) & 0xFF)
}
), %A_startup%\%ScheduledTime%_%Filename%.ahk
}
Edit 2006-09-03: Changed GUI (thanks Bobo)