.NET FileInfo.LastWriteTime & FileInfo.LastAccessTime are wrong
Asked Answered
E

7

28

When I call FileInfo(path).LastAccessTime or FileInfo(path).LastWriteTime on a file that is in the process of being written it returns the time that the file was created, not the last time it was written to (ie. now).

Is there a way to get this information?

Edit: To all the responses so far. I hadn't tried Refresh() but that does not do it either. I am returned the time that the file was started to be written to. The same goes for the static method, and creating a new instance of FileInfo.

Codymanix might have the answer, but I'm not running Windows Server (using Windows 7), and I don't know where the setting is to test.

Edit 2: Nobody finds it interesting that this function doesn't seem to work?

Emmyemmye answered 19/9, 2009 at 15:5 Comment(3)
I've also found these functions give unreliable information; like when the file resides on a (samba) network share. I noticed MSDN docs ( msdn.microsoft.com/en-us/library/… ) now says "This method may return an inaccurate value ..."Lightening
It is interesting that the function doesn't work - it seems that it is not possible, on windows, to get the last modified date of a file. It seems there is also no available workaround. Your application will have to poll the file and hash its entire contents if it wants to absolutely know if the file has changed.Vaenfila
I ran over this problem with a .NET 6 application on linux. I wanted to know if a file was modified or not. After some testing, I made sure that the process that used the file was disposed and I wait 5 seconds before refreshing the fileinfo. Not elegant, but seems to work.Suicidal
K
16

The FileInfo values are only loaded once and then cached. To get the current value, call Refresh() before getting a property:

f.Refresh();
t = f.LastAccessTime;

Another way to get the current value is by using the static methods on the File class:

t = File.GetLastAccessTime(path);
Kiefer answered 19/9, 2009 at 15:8 Comment(1)
t = File.GetLastAccessTime(path); is still out of date if a process has saved but is locking the file. This answer is incorrect.Dropper
A
9

Starting in Windows Vista, last access time is not updated by default. This is to improve file system performance. You can find details here:

https://techcommunity.microsoft.com/t5/storage-at-microsoft/disabling-last-access-time-in-windows-vista-to-improve-ntfs/ba-p/423328

To reenable last access time on the computer, you can run the following command:

fsutil behavior set disablelastaccess 0

Avert answered 7/12, 2010 at 20:29 Comment(0)
F
5

As James has pointed out LastAccessTime is not updated.


The LastWriteTime has also undergone a twist since Vista. When the process has the file still open and another process checks the LastWriteTime it will not see the new write time for a long time -- until the process has closed the file.

As a workaround you can open and close the file from your external process. After you have done that you can try to read the LastWriteTime again which is then the up to date value.


File System Tunneling:

If an application implements something like a rolling logger which closes the file and then renames it to a different file name you will also run into issues since the creation time and file size of the "old" file is remembered by the OS although you did create a new file. This includes wrong reports of the file size even if you did recreate log.txt from scratch which is still 0 bytes in size. This feature is called OS File System Tunneling which is still present on Windows 8.1 . An example how to work around this issue check out RollingFlatFileTracelistener from Enterprise Library.

You can see the effects of file system tunneling on your own machine from the cmd shell.

echo test > file1.txt
ren file1.txt file2.txt
Wait one minute
echo test > file1.txt

dir  /tc file*.txt
...
05.07.2015  19:26                 7 file1.txt
05.07.2015  19:26                 7 file2.txt

The file system is a state machine. Keeping states correctly synchronized is hard if you care about performance and correctness.

This strange tunneling syndrome is obviously still used by application which do e.g. autosave a file and move it to a save location and then recreate the file again at the same location. For these applications it makes to sense to give the file a new creation date because it was only copied around. Some installers do also such tricks to move files temporarily to a different location and write the contents back later to get past some file exists check for some install hooks.

Fleawort answered 5/7, 2015 at 19:15 Comment(0)
R
4

Have you tried calling Refresh() just before accessing the property (to avoid getting a cached value)? If that doesn't work, have you looked at what Explorer shows at the same time? If Explorer is showing the wrong information, then it's probably something you can't really address - it might be that the information is only updated when the file handle is closed, for example.

Reichel answered 19/9, 2009 at 15:7 Comment(0)
C
4

From MSDN:

When first called, FileSystemInfo calls Refresh and returns the cached information on APIs to get attributes and so on. On subsequent calls, you must call Refresh to get the latest copy of the information.

FileSystemInfo.Refresh()

If you're application is the one doing the writing, I think you are going to have to "touch" the file by setting the LastWriteTime property your self between each buffer of data you write. Some psuedocode:

while(bytesWritten < totalBytes)
{
   bytesWritten += br.Write(buffer);
   myFileInfo.LastWriteTime = DateTime.Now;
}

I'm not sure how severely this will affect write performance.

Conveyancer answered 19/9, 2009 at 15:8 Comment(0)
K
4

There is a setting in windows which is sometimes set especially on server systems so that modified and accessed times for files are not set for better performance.

Kissable answered 19/9, 2009 at 15:49 Comment(3)
codymanix is right, they talk about this setting here: blogs.technet.com/b/filecab/archive/2006/11/07/…Janik
That link only mentions last-modified-time.Spancel
@RogerLipscombe It states: "we’ve disabled updates to Last Access Time". It does briefly mention last modified time but it doesn't seem to be saying that it is no longer updated.Quadrangle
I
0

Tommy Carlier's answer got me thinking....

A good way to visualise the differences is seperately running the two snippets (I just used LinqPAD) simliar to below while also running sysinternals Process Monitor.

while(true)
    File.GetLastAccessTime([file path here]);

and

FileInfo bob = new FileInfo(path);

while(true){
    string accessed = bob.LastAccessTime.ToString();
}

If you look at Process Monitor while running the first snippet you will see repeated and constant access attempts to the file for the LinqPAD process. The second snippet will do an initial access of the file, for which you will see activity in process monitor, and then very little afterwards.

However if you go and modify the file (I just opened the text file I was monitoring using FileInfo and added a character and saved) you will see a series of access attempts by the LinqPAD process to the file in process monitor.

This illustrates the non-cached and cached behaviour of the two different approachs respectively.

Will the non-cached approach wear a hole in the hard drive?!

EDIT

I went away feeling all clever over my testing and then used the caching behaviour of FileInfo in my windows service (basically to sit in a loop and say 'Has-file-changed-has-file-changed...' before doing processing)

While this approach worked on my dev box, it did not work in the production environment, ie the process just kept running regardless if the file had changed or not. I ended up changing my approach to checking and just used GetLastAccessTime as part of it. Don't know why it would behave differently on production server....but I am not too concerned at this point.

Ibadan answered 25/10, 2012 at 5:53 Comment(1)
Eventually yes, as well as time and space.Titanium

© 2022 - 2024 — McMap. All rights reserved.