There is an MSDN blog describing why Windows behaves as you describe it.
First let's mention that what you see is only on NTFS.
To test what you said I wrote a small program that writes 40 kB to a file every 5 seconds. The file is kept open between every write. A second program uses FindFirstFileEx
to get the current file size. As third I use dir
in cmd.exe. With this setup I can exactly see what you describe.
The cause of this issue is a design decision taken in NTFS. In NTFS (as in Unix filesystem) the same file can be in two directories - this is called a hardlink. This means you have two directories, each having an entry for the file and you have the file itself with it's properties. File size is a property that belongs to the file, so it is stored there. But, if someone wants a list of the files in a directory with properties like file size, then you would have very low performance if you had not only to read the directory itself but also read information from every file. Data for one directory is likely to be stored sequentially, but data for different files is likely to be scattered all over the disc. Therefore NTFS stores a copy of the file size in the directory entry/entries.
You might have guessed it, this also has a performance hit. Think about 10 hardlinks to the same file. Do you want NTFS to update 10 directory entries every time you write to a file? No. So a second design decision was made since Vista: data in the directory entry is only updated when the file is closed.
You can easily check that: run a program that writes to a file and keeps the file open. Run dir
and you will not see an updated size. Or write a file with Notepad (which closes the file at the end) and immediately the new file size is displayed in dir
or Explorer.
How come that F5 helps refreshing the file size? Explorer calls GetNamedSecurityInfo which internally opens the file and closes it (you can check that in SysInternals Process Monitor). If I call GetNamedSecurityInfo
in my own program and then call FindFirstFileEx
I see the new file size immediately. So the observed behavior is exactly as expected from theory.
But why don't you see the new file size immediately in Explorer? It seems that Explorer is first calling FindFirstFileEx
and then GetNamedSecurityInfo
. So Explorer is getting the old size and then triggers updating the directory entry. If you run dir
in cmd.exe you can see that the directory entry now has the new file size. It is only that Explorer does not yet know it. It takes Explorer a second F5 to get the latest size and then again trigger an update.
From an application developers view I would not consider this an Explorer bug - this is a special case for one of the supported file systems, and an application should abstract from the file systems. But as Explorer is part of Windows I tend to think that Microsoft could have done better and changed the order of the function calls to get a better user experience.
BTW, thanks for that very interesting question! I like having learned such NTFS interna.