A_Now versus FileGetTime() timestamps
A_Now versus FileGetTime() timestamps
When a script is launched, the launch time is obtained using the "A_Now" variable. A timer is then started to check the modification time of included files against the launch time and, if an included file has has a later date, the "Reload" command is issued. The issue is that the reloaded script, which again retrieves its launch time using the "A_Now" variable, often receives a time that is a second earlier then the modification time of the file which caused the reload, resulting is a second reload. Is there a known issue with the rounding of milliseconds in the timestamp returned by the "A_Now" command verses the timestamp returned by the FileGetTime() command that could cause a script started after a file was saved to report an "A_Now" time that is a second earlier than the saved file?
Re: A_Now versus FileGetTime() timestamps
What is your question? Where is your script? It sounds like you want to reload a script automatically, when a included file is updated?
If No, I can't tell the question, but I can tell A_Now is not a command, and the launch time is not suitable for the task.
If No, I can't tell the question, but I can tell A_Now is not a command, and the launch time is not suitable for the task.
Re: A_Now versus FileGetTime() timestamps
Thanks wolf_II for taking the time to reply. Yes, A_Now is not a command. It's a variable as stated in the first sentence. My mistake.
My last sentence asks the question I have although I admit that it may be difficult to understand.
The following script shows the problem. Copy the script into a file and create an "externalFile.txt" file in the same directory. Launch the script and then update the external file's modification date (open the externalFile.txt in an editor, add some text, save the file). The script will detect that the external file's modification time has change and reload the script (as designed). The problem is that when the script is reloaded it detects again that the external file's modification timestamp is later than the new script launch time and reloads the file a second time. This can be observed by watching the script's tray icon flash twice. To see, what I believe to be the root cause, un-comment the "FileAppend ..." code. It will create a logFile.txt file in the same directory containing the compared timestamp values that caused the reloads to occur.
My last sentence asks the question I have although I admit that it may be difficult to understand.
The following script shows the problem. Copy the script into a file and create an "externalFile.txt" file in the same directory. Launch the script and then update the external file's modification date (open the externalFile.txt in an editor, add some text, save the file). The script will detect that the external file's modification time has change and reload the script (as designed). The problem is that when the script is reloaded it detects again that the external file's modification timestamp is later than the new script launch time and reloads the file a second time. This can be observed by watching the script's tray icon flash twice. To see, what I believe to be the root cause, un-comment the "FileAppend ..." code. It will create a logFile.txt file in the same directory containing the compared timestamp values that caused the reloads to occur.
Code: Select all
#Persistent
;Check external file every second
SetTimer, ReloadCheck, 1000
ReloadCheck()
{
;Script launch timestamp
Static launchTime := A_Now
;External file's modification time
FileGetTime, fileTime, externalFile.txt
;File modified after script launched?
if( fileTime > launchTime )
{
;FileAppend, % fileTime . " > " . launchTime . "`n", logFile.txt
Reload
}
}
Re: A_Now versus FileGetTime() timestamps
Thx for the clarification, My point was, IF the only reason for your work is To AUTO_Reload, I have a better way.
IMHO, A_Now and Launch time are not suitable for the task. As you found out.
File timestamps are ok, but you need to remember them, and compare. Independent from Lauch-time.
Try this : (by putting it in Main.ahk)
IMHO, A_Now and Launch time are not suitable for the task. As you found out.
File timestamps are ok, but you need to remember them, and compare. Independent from Lauch-time.
Try this : (by putting it in Main.ahk)
Code: Select all
#Include AutoReload.ahk
oARL.add("Path\to\File")
Code: Select all
;-------------------------------------------------------------------------------
AutoReload() { ; init
;-------------------------------------------------------------------------------
oARL := new AutoReload
; auto-reload when any file in Include or Lib folder changes
Loop, Parse, % "Include, Lib", `,, %A_Space%
Loop, Files, %A_LoopField%\*.*
oARL.Add(A_LoopFileLongPath)
Return, oARL
}
;===============================================================================
class AutoReload { ; auto-reload script when a file changes
;===============================================================================
;---------------------------------------------------------------------------
__New() { ; the constructor starts the timer
;---------------------------------------------------------------------------
FileGetTime, TimeStamp, %A_ScriptFullPath%
this.Push({File: A_ScriptFullPath, Time: TimeStamp})
SetTimer, %this% ; uses Call()
}
;---------------------------------------------------------------------------
Add(FileFullPath) { ; add a file to monitor
;---------------------------------------------------------------------------
FileGetTime, TimeStamp, %FileFullPath%
this.Push({File: FileFullPath, Time: TimeStamp})
}
;---------------------------------------------------------------------------
Call() { ; check the time stamps of all the files
;---------------------------------------------------------------------------
Loop, % this.MaxIndex() {
File := this[A_Index].File
FileGetTime, TimeStamp, %File%
If (TimeStamp = this[A_Index].Time)
Continue ; do nothing yet
; a file has changed
SetTimer, %this%, Off
If A_IconHidden {
ToolTip, Reloading ...`n%File%
SoundPlay, *-1
} Else
TrayTip, Reloading ..., %File%,, 1
Sleep, 2000
Reload
; if reload fails, turn timer back on
this[A_Index].Time := TimeStamp
SetTimer, %this%, On
ToolTip ; off
TrayTip ; off
}
}
}
Re: A_Now versus FileGetTime() timestamps
I have not tested my script recently, I used to have some problems with TrayTip, which are gone now.
If have problems with my class, please come back, and paste a script of yours, and I can now start to test again.
There is an Init() function in there that might not be of interest to you.
If have problems with my class, please come back, and paste a script of yours, and I can now start to test again.
There is an Init() function in there that might not be of interest to you.
Re: A_Now versus FileGetTime() timestamps
You should add return/Exit/ExitApp, as appropriate, after Reload. If you don't, the script may still perform some actions before finally closing.
For this script, maybe ExitApp is necessary.
Alternatively, perhaps you should turn SetTimer off, before Reload.
Perhaps, a new script is starting, while the old script is still modifying the file. I haven't checked fully.
Code: Select all
Reload
return
Alternatively, perhaps you should turn SetTimer off, before Reload.
Perhaps, a new script is starting, while the old script is still modifying the file. I haven't checked fully.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
- flyingDman
- Posts: 2791
- Joined: 29 Sep 2013, 19:01
Re: A_Now versus FileGetTime() timestamps
IMHO the script's behavior is greatly impacted by the declaration of the static variable. The help file states Each static variable is initialized only once (before the script begins executing). And again in the example given: A static declaration's initializer still runs only once (upon startup).
so that unless reloaded, the LaunchTime only gets updated during the first time the script runs. So without the Reload at the end of the function fileTime > launchTime if true once, will remain true. If you were to replace static launchTime := A_Now with fileTime > launchTime would never be true (unless the clock of the PC generating externalFile.txt goes haywire...)
I think this is what you're looking for:
To check if this works (it does here), run this after launching the script above:
The 1st script should generate a beep every time the second script runs. I.e. every time the file gets a new modified date.
so that unless reloaded, the LaunchTime only gets updated during the first time the script runs. So without the Reload at the end of the function fileTime > launchTime if true once, will remain true. If you were to replace static launchTime := A_Now with
Code: Select all
static launchTime := A_Now
launchTime := A_Now
I think this is what you're looking for:
Code: Select all
#Persistent
launchTime := A_Now
SetTimer, ReloadCheck, 1000
return
ReloadCheck: ;I don't think a function is needed
FileGetTime, fileTime, externalFile.txt
if( fileTime > launchTime )
{
soundbeep,1000,50
launchTime := A_Now
;other stuff ; reload not necessary
}
return
Code: Select all
fileappend,abc`n,externalFile.txt
Last edited by flyingDman on 07 Jul 2019, 10:17, edited 1 time in total.
14.3 & 1.3.7
Re: A_Now versus FileGetTime() timestamps
I appreciate the suggestions but my initial question has not been answered. In short, a script is reloaded and then 1 second later, when the first timer event occurs, the current system time is retrieved using A_Now and it is an earlier timestamp than the modification time of a file saved before the script was reloaded. Is there that much variability in the setting of a file's modification time and/or the A_Now timestamp?
Unless someone can point out a problem with the code, I'll work around the problem by increasing the timer period (delays the setting of the launch time) or by adding a couple of seconds to the launch time using Static launchTime := A_Now + 2.
Unless someone can point out a problem with the code, I'll work around the problem by increasing the timer period (delays the setting of the launch time) or by adding a couple of seconds to the launch time using Static launchTime := A_Now + 2.
- flyingDman
- Posts: 2791
- Joined: 29 Sep 2013, 19:01
Re: A_Now versus FileGetTime() timestamps
I attempted to tell you, using quotes from the help file, that that is not the case. The current system time is retrieved once upon startup of the script, and not when the timer runs.a script is reloaded and then 1 second later, when the first timer event occurs, the current system time is retrieved
Run this to convince yourself:
Code: Select all
settimer,timer, 1000
return
esc::
msgbox % res
exitapp
timer()
{
global res
static launchTime := A_Now
return res .= launchTime "`n"
}
Let this run for a few seconds and then press esc. Launchtime is not updated and the same time is shown multiple times. Add one line launchTime := A_Now just below the line static launchTime := A_Now and you'll see that launchtime does get updated.
So, your script as it is, does not accomplish what you want and giving unwanted results.
14.3 & 1.3.7
- flyingDman
- Posts: 2791
- Joined: 29 Sep 2013, 19:01
Re: A_Now versus FileGetTime() timestamps
Run this as well for a few seconds and then press esc. The first value is that of launchtime2, all values below that are of launchtime. They are all the same. So static launchTime := A_Now
is launched at the time the script is launched I.e at the same time launchTime2 := A_Now and not 1 second later.
is launched at the time the script is launched I.e at the same time launchTime2 := A_Now and not 1 second later.
Code: Select all
#persistent
launchTime2 := A_Now
settimer,timer, 1000
return
esc::
msgbox % launchtime2 "`n`n`" res
exitapp
timer()
{
global res
static launchTime := A_Now
return res .= launchTime "`n"
}
14.3 & 1.3.7
Re: A_Now versus FileGetTime() timestamps
Thanks flyingDman for reminding me of the fact that launchTime is assigned when the script is launched and for taking the time to write the code to prove it. That helps to better explain, although still surprising, why 2 seconds needs to be added to A_Now in order to insure the launchTime timestamp is equal to or later than the fileTime timestamp.
Re: A_Now versus FileGetTime() timestamps
The 2 second difference between the actual file write time and the file's reported modified date was due to the file being stored on a FAT32 formatted drive. A search for "FAT32 timestamp resolution" returned the following:
Note: USB flash drives, SD cards, and other removable drives still using FAT32.
Running the test code on a NTFS file system worked without the need to add 2 seconds.NTFS stores all timestamps to 100 nanosecond resolution. By comparison, FAT32 stores the time portion of a timestamp to a 2 second resolution.
Note: USB flash drives, SD cards, and other removable drives still using FAT32.
Who is online
Users browsing this forum: Google [Bot], JoeWinograd, MiM, TAC109 and 141 guests