nughtin
15th November 2011 14:22 UTC
GetFileTime vs GetFileTimeLocal yields different results
If I do a GetFileTimeLocal on a file, install it, then do a GetFileTime on that same file it gives different results. The timezones on the build computer and the computer i am installing on are the same. Can anyone help?
Code:
GetFileTime ${destfile} $R0 $R1 ; File it will be replacing
GetFileTimeLocal ${localfile} $R2 $R3 ; File to install
DetailPrint "Existing File=${destfile}"
DetailPrint "Existing File=$R0.$R1"
DetailPrint "New File=${localfile}"
DetailPrint "New File=$R2.$R3"
IntCmp $R0 $R2 0 "installlibbydate.start_${INSTALLLIBBYDATE_UNIQUE}" "installlibbydate.done_${INSTALLLIBBYDATE_UNIQUE}"
IntCmp $R1 $R3 "installlibbydate.done_${INSTALLLIBBYDATE_UNIQUE}" "installlibbydate.start_${INSTALLLIBBYDATE_UNIQUE}" "installlibbydate.done_${INSTALLLIBBYDATE_UNIQUE}"
Results:
Existing File=C:\Documents and Settings\XPMUser\Desktop\NSIS Testing\AspenAI.dll
Existing File=30188312.338555648
New File=C:\Development\Aspen2000\bin\AspenAI.dll
New File=30188312.356245648
Anders
15th November 2011 15:38 UTC
From MSDN:
Not all file systems can record creation and last access times and not all file systems record them in the same manner. For example, on FAT, create time has a resolution of 10 milliseconds, write time has a resolution of 2 seconds, and access time has a resolution of 1 day (really, the access date). Therefore, the GetFileTime function may not return the same file time information set using the SetFileTime function.
I'm guessing this is the issue, so you should probably add a fuzz factor of about 4 seconds. Or you could try calling CompareFileTime() with the system plugin, but I'm not sure if it does any fuzzing...
demiller9
15th November 2011 16:17 UTC
The getfiletime/getfiletimelocal commands are ok, the problem starts in makensis: the compiler truncates file times to a 2 second resolution. I think this is so the 'ifnewer' attribute will succeed when extracting to FAT volumes.
nughtin
15th November 2011 16:34 UTC
Thanks. Both posts are very helpful. I'll try to figure out how to either truncate the file time to a 2 second resolution or add a fuzz factor of 4 seconds or so. I've been having some difficulty finding documentation on doing this so if anyone knows how to do this your help would be appreciated.
Anders
15th November 2011 16:49 UTC
It might be a bug if makensis fuzzes the time and the exehead does not
nughtin
15th November 2011 17:32 UTC
Thanks for the help. I think I got this working. Let me know if you see anything wrong.
!macro ConvertFileTimeToInt64 out high low
System::Int64Op ${high} * 4294967296
Pop ${out}
System::Int64Op ${out} + ${low}
Pop ${out}
System::Int64Op ${out} / 10000000
Pop ${out}
!macroend
...
GetFileTime ${destfile} $R0 $R1 ; File it will be replacing
!insertmacro ConvertFileTimeToInt64 $R2 $R0 $R1
GetFileTimeLocal ${localfile} $R0 $R1 ; File to install
!insertmacro ConvertFileTimeToInt64 $R3 $R0 $R1
System::Int64Op $R3 - $R2
Pop $R4
DetailPrint "Existing File=${destfile}"
DetailPrint "Existing File=$R0"
; DetailPrint "New File=${localfile}"
DetailPrint "New File.....=$R2"
DetailPrint "Difference...=$R3"
IntCmp $R4 4 "installlibbydate.skip_${INSTALLLIBBYDATE_UNIQUE}" "installlibbydate.skip_${INSTALLLIBBYDATE_UNIQUE}" "installlibbydate.start_${INSTALLLIBBYDATE_UNIQUE}"
Anders
15th November 2011 18:26 UTC
Why are you not using "SetOverwrite ifnewer" and letting NSIS take care of it for you? (There is a bug here also but it will be fixed when we figure out what to do about it)
nughtin
15th November 2011 18:45 UTC
These are COM DLL's that need to be unregistered if it is determined that the file is newer. We will only use this method for DLL's that our company writes. We can't go based on the DLL version because it doesn't always change between builds.