Archive: Understanding GetFileTime


Understanding GetFileTime
  I am trying to work with this function. I read, using the search, that we have to compare resulting variables with IntCmpU (Unsigned), but testing with GetFileTime I see that sometimes it returns negative numbers.

Another thing, how can I get the minutes and seconds from that number? I want that to calculate elapsed time, but it can be useful to calculate current date/time if compared with a file of known date (then we don't have to use a dll:))


http://forums.winamp.com/showthread....ight=file+time


Thanks kichik, that was one of the threads I read before posting.:)

I still don't understand "I use IntCmpU because a DWORD is an unsigned long" because, as I say in my first post, sometimes GetFileTime returns a signed number. Does sounds to me as a contradiction.


You see it as a signed number because that's how you look at it. Both signed and unsigned numbers are saved as bits of 0 or 1, and the sign depends on how you treat them. If you look at them as signed numbers they will have a sign, if you don't they won't.


So, the good way to look at those numbers is as unsigned, ok. But I didn't decide which way I look at those numbers, I just made a DetailPrint.

The other question: Is there a way I can pull seconds and minutes from that number?

Thanks for being so patient
:)


It's not the good way, it's THE way ;)

You will have to use brainsucker's System.dll to do this calculation. The FILETIME (which is used to get these two numbers) structure is a 64-bit value representing the number of 100-nanosecond intervals since January 1, 1601 (UTC). I am sorry but I am pretty busy right now so I won't be able to help you with the script... Maybe brainsucker will be able to help you, he know his DLL better than I do anyway :D


I've included such example into just posted release (Sample 6). See examples/system.nsi.


Originally posted by kichik
is a 64-bit value representing the number of 100-nanosecond intervals
So, I can divide for 10^7 and get seconds, isn't it?

hm... there will be a little problem, since GetFileTime return this time as two DWORDS, time=DW1*4294967296+DW2... So you have to do a little calculations.


some calculations? just a substraction, or two because we have two dwords.

Anyway it's better this than have to work with a dll.

Are there any plans to add GetCurrentTime function to nsis? Otherwise a function can be made for this.


Two substractions, one multiplication and one addition. ;)

Yes you are right, it's easier... if you are planning to use that for delta-times (differences between two times).


So what is the actual script for converting GetFileTime high and low dwords into readable hours and minutes?

eg. x:xx

This script should be written down on the NSIS archive.
-Stuart


Originally posted by Afrow UK
So what is the actual script for converting GetFileTime high and low dwords into readable hours and minutes?

eg. x:xx

This script should be written down on the NSIS archive.
-Stuart
Well, it's more or less in the archive :p The title is "report elapsed time at the end" or something like this.

Anyway, to get seconds from that double number (as I said before) you only need to divide by 10000000.

If you still need the code here it is:

GetTempFileName $R5

GetFileTime $R5 $R6 $R7
IntOp $R7 $R7/ 10000000
>
This three lines are copied and pasted from that script :eek:

This code don't work rightly if pass some minutes (if you for example add a hour to Windows Clock before the detection of the install end time with the example "report elapsed time at the end")...


I attempted to use that before, but it was screwing up and giving me minus times.


I have just used the plugin instead...

http://myweb.tiscali.co.uk/imker/afr...ads/nsisdt.zip

This plugin dll allows you to enter like 15 different combinations of dates and/or times into your app.

Special thanks to Rainwater for writing the plugin :)

-Stuart


But I beleave that have a bug in this NSISdt:

oct/28 until feb/08 - show -1 hour (i.e. 01/01/2003 00:30 show 31/12/2002 23:30 !).

mar/7 until oct/20 - show +1 hour (i.e. 04/30/2003 23:30 show 05/01/2003 00:30 !).

I've sended a PM to the rainwater and he read, but not replied my message until now.


? 31/12/2002? Whoops, is 12/31/2002.

oct/28 -> feb/08 - show -1 hour (i.e. 01/01/2003 00:30 show 12/31/2002 23:30 !).

mar/7 -> oct/20 - show +1 hour (i.e. 04/30/2003 23:30 show 05/01/2003 00:30 !).


I believe that's because the function called in NSISdt is taking the day light saving time into consideration. I don't see anything wrong with that.


-1 or +1 hour of original time. In my computer for example the clock is showing now 14:29, now the NSISdt show normal (we are between feb/8 and mar/7), but after mar/7 will show +1 hour of original time (the time here will not to be in the summer time!), after oct/20 will show the original time, and after oct/28 will show -1 hour (when the time here will be in the summer time). Now it's more explained, isn't it?


And a question, how I can use the "systemGetFileSysTime demo" in the System.nsi? Ever when I use this in a script, give me a error:

"This program run an ilegal operation and will be close"


Output "C:\Test.exe"

>Caption "Test"

>!include "${NSISDIR}\\Contrib\\System\\sysfunc.nsh"

>Section
!insertmacro smGetFileSysTime $CMDLINE
System
::Call '*$R0${stSYSTEMTIME}(.r1, .r2, .r3, .r4, .r5, .r6, .r7, .r8)'

MessageBox MB_OK "GetFileSysTime example: file '$CMDLINE', year $1, month $2, dow $3, day $4, hour $5, min $6, sec $7, ms $8"

; free memory from SYSTEMTIME
System::Free $R0
SectionEnd
>

Hm... I see no reasons for "This program run an ilegal operation and will be close" message here. :)
In fact I've found a small bug in this code example - $CMDLINE may return for installer.exe name in double quotes, or with some parameters, so I've changed scripts a bit (Could Kichik or some one else update CVS version please ;). See bellow for script which works fine for me at win98/xp (you should first update sysfunc.nsh from attached zip). Reply if you'll have more problems, please.


Name "System Plugin Example"

>OutFile "date.exe"
>SetPluginUnload alwaysoff

>!include "${NSISDIR}\Contrib\System\sysfunc.nsh"

>Section "ThisNameIsIgnoredSoWhyBother?"
SetOutPath $TEMP

; ----- Sample 6 ----- systemGetFileSysTime demo -----
Call GetInstallerExeName
pop $0

!insertmacro smGetFileSysTime $0
System
::Call '*$R0${stSYSTEMTIME}(.r1, .r2, .r3, .r4, .r5, .r6, .r7, .r8)'

MessageBox MB_OK "GetFileSysTime example: file '$0', year $1, month $2, dow $3, day $4, hour $5, min $6, sec $7, ms $8"

; last plugin call must not have /NOUNLOAD so NSIS will be able to delete the temporary DLL
SetPluginUnload manual

; free memory from SYSTEMTIME
System::Free $R0

SectionEnd
>

Done.


After downloading these new files, I've tested this example and didn't show any error messages, but the result of all values (year, month, day of week...) are 0:

GetFileSysTime example: file 'C:\path\date.exe', year 0, month 0, dow 0, day 0, hour 0, min 0, sec 0, ms 0

And I've detected a new bug with another example in System.nsi:

Show a blue screen after another when I execute the compiled example 1 - Message box with custom icon, here is the script:


Name "System Plugin Example 1"

>OutFile "CustomMessageBox.exe"
>SetPluginUnload alwaysoff

>!include "${NSISDIR}\\Contrib\\System\\sysfunc.nsh"

>Section "ThisNameIsIgnoredSoWhyBother?"
SetOutPath $TEMP

; ----- Sample 1 ----- Message box with custom icon -----

!
insertmacro smMessageBox "i 0" "Message box with custom icon!" "System Example 1a" ${MB_OK} "i 103"
; i 0 - installer exe as module
; i 103 - icon ID

; The same example but using icon from resource.dll.
;You could use this dll for storing your resources, just replace FAR icon
; with something you really need.
File "${NSISDIR}\\Contrib\\System\\Resource.dll"
!insertmacro smMessageBox "`$TEMP\\resource.dll`" "Message box with custom icon from resource.dll!" "System Example 1b" ${MB_OK} "i 103"
Delete $TEMPresource.dll

SectionEnd
>

Could you report, please, which windows version you are using?
System.nsi shows blue screen too? If so could you please cut and test smaller samples from it (like 3, 4 and 5). If they'll run ok, then it will be best to find exact place giving blue screen (by cutting and testing separate actions from 1 sample (system::calls at systemMessageBox proc at sysfunc.nsh)). If not.... hm...

getfiletime could return zero values when it couldn't find the file. Again - see no reasons. Could you please insert after the call to sysFindFirstFile (at sysfunc) the next line:

MessageBox MB_OK "$1 $2 $3"

and post here the message box text.


Could you report, please, which windows version you are using?
Windows 98 Second Edition

System.nsi shows blue screen too? If so could you please cut and test smaller samples from it (like 3, 4 and 5). If they'll run ok, then it will be best to find exact place giving blue screen (by cutting and testing separate actions from 1 sample (system::calls at systemMessageBox proc at sysfunc.nsh)). If not.... hm...
Now I cannot do this now (Connected to Internet, if gives the blue screen now the connection will be lost), but tomorrow I will report at here. Only that I know now, it occours when it try to insert the icon in the messagebox, after this show two blue screens ,show a message that the system is warningly lack of resources, and make a loop with the blue screens and this message.

getfiletime could return zero values when it couldn't find the file. Again - see no reasons. Could you please insert after the call to sysFindFirstFile (at sysfunc) the next line:

MessageBox MB_OK "$1 $2 $3"

and post here the message box text.
Show:



:) Nothing! :)

I had track for bugs at this morning on the example 1, and saw on what line that occours this error, there is the line:

System::Call '${sysFreeLibrary}(r1)'

The line "IntCmp $2 0 0 smbskipfree smbskipfree" ever continue to this line above, because the line
"System::Call '${sysGetModuleHandle}($2) .r1'" don't return the handle, because the line
"System::Call '${sysLoadLibrary}($2) .r1'" don't load the module.

In the first !insertmacro line of the file that contain the "System Plugin Example 1" (not System.nsi),
the module that is pushed to stack is "i 0", return this value at line "System::Call '${sysLoadLibrary}($2) .r1'"
(file SysFunc.nsh), return this value at "System::Call '${sysGetModuleHandle}($2) .r1'" (file SysFunc.nsh),
continue in the line "IntCmp $1 0 0 smbnext smbnext" (file SysFunc.nsh) and go at the problem line
"System::Call '${sysGetModuleHandle}($2) .r1'" (file SysFunc.nsh), after this show blue screens after another.