.NET FileInfo.LastWriteTime & FileInfo.LastAccessTime неверны - PullRequest
21 голосов
/ 19 сентября 2009

Когда я вызываю FileInfo(path).LastAccessTime или FileInfo(path).LastWriteTime для файла, который находится в процессе записи, он возвращает время, когда файл был создан, а не последний раз, когда он был записан (т.е. сейчас).

Есть ли способ получить эту информацию?

Редактировать: На все ответы до сих пор. Я не пробовал Refresh(), но это тоже не делает. Мне возвращается время начала записи файла. То же самое касается статического метода и создания нового экземпляра FileInfo.

Codymanix может иметь ответ, но у меня не работает Windows Server (используется Windows 7), и я не знаю, где настройка для тестирования.

Редактировать 2: Никому не интересно, что эта функция не работает?

Ответы [ 7 ]

14 голосов
/ 19 сентября 2009

Значения FileInfo загружаются только один раз и затем кэшируются. Чтобы получить текущее значение, позвоните Refresh() до получения свойства:

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

Другой способ получить текущее значение - использовать статические методы класса File:

t = File.GetLastAccessTime(path);
8 голосов
/ 07 декабря 2010

Начиная с Windows Vista, время последнего доступа по умолчанию не обновляется. Это должно улучшить производительность файловой системы. Вы можете найти детали здесь:

http://blogs.technet.com/b/filecab/archive/2006/11/07/disabling-last-access-time-in-windows-vista-to-improve-ntfs-performance.aspx

Чтобы снова включить время последнего доступа к компьютеру, вы можете выполнить следующую команду:

fsutil поведенческий набор disablelastaccess 0

4 голосов
/ 05 июля 2015

Как указал Джеймс LastAccessTime не обновляется .


LastWriteTime также претерпел изменения с Vista. Когда у процесса есть файл, который все еще открыт, и другой процесс проверяет LastWriteTime, он не будет видеть новое время записи в течение длительного времени - пока процесс не закроет файл.

В качестве обходного пути вы можете открывать и закрывать файл из внешнего процесса. После того, как вы это сделаете, вы можете попытаться снова прочитать LastWriteTime, который является последним значением.


Туннелирование файловой системы:

Если в приложении реализовано что-то вроде скользящего регистратора, который закрывает файл и затем переименовывает его в другое имя файла, у вас также будут возникать проблемы, так как время создания и размер файла "старого" файла запоминаются ОС, хотя Вы создали новый файл. Это включает в себя неправильные отчеты о размере файла, даже если вы воссоздали log.txt с нуля, который по-прежнему имеет размер 0 байт. Эта функция называется туннелированием файловой системы ОС, которая все еще присутствует в Windows 8.1. Пример того, как обойти эту проблему, можно найти в RollingFlatFileTracelistener из Enterprise Library .

Вы можете увидеть эффекты туннелирования файловой системы на своем компьютере из оболочки cmd.

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

Файловая система является конечным автоматом. Правильно синхронизировать состояния сложно, если вы заботитесь о производительности и правильности.

Этот странный туннельный синдром, очевидно, все еще используется приложением, которое, например, автоматически сохраните файл и переместите его в место сохранения, а затем заново создайте файл в том же месте. Для этих приложений имеет смысл дать файлу новую дату создания, потому что он был только скопирован. Некоторые установщики также делают такие приемы, чтобы временно переместить файлы в другое место и записать содержимое позже, чтобы обойти какой-либо файл, проверить наличие некоторых хуков установки.

4 голосов
/ 19 сентября 2009

В Windows есть настройка, которая иногда устанавливается, особенно в серверных системах, чтобы время изменения и обращения к файлам не устанавливалось для повышения производительности.

4 голосов
/ 19 сентября 2009

Из MSDN:

При первом вызове FileSystemInfo вызывает Refresh и возвращает кэшированная информация об API для получения атрибуты и тд. На последующем звонки, вы должны позвонить Обновить, чтобы получить последняя копия информации.

FileSystemInfo.Refresh ()

Если ваше приложение - приложение, которое пишет, я думаю, вам придется «дотронуться» до файла, установив свойство LastWriteTime самостоятельно между каждым буфером данных, который вы пишете. Какой-то псевдокод:

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

Я не уверен, насколько сильно это повлияет на производительность записи.

4 голосов
/ 19 сентября 2009

Вы пытались вызвать Refresh() непосредственно перед доступом к свойству (чтобы избежать получения кэшированного значения)? Если это не работает, вы смотрели на то, что показывает Explorer одновременно? Если в проводнике отображается неверная информация, то, возможно, это то, к чему вы не можете по-настоящему обратиться - возможно, информация обновляется только тогда, когда дескриптор файла закрыт, например.

0 голосов
/ 25 октября 2012

Ответ Томми Карлера заставил меня задуматься ...

Хороший способ визуализации различий заключается в том, чтобы по отдельности запустить два фрагмента (я только что использовал LinqPAD), а также запустить sysinternals Process Monitor.

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

и

FileInfo bob = new FileInfo(path);

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

Если вы посмотрите на Process Monitor при запуске первого фрагмента, вы увидите повторные и постоянные попытки доступа к файлу для процесса LinqPAD. Второй фрагмент сделает начальный доступ к файлу, для которого вы увидите активность в мониторе процесса, а затем совсем немного.

Однако, если вы перейдете и измените файл (я только что открыл текстовый файл, который я отслеживал, используя FileInfo, добавил символ и сохранил), вы увидите серию попыток доступа процесса LinqPAD к файлу в мониторе процесса.

Это иллюстрирует не кэшированное и кэшированное поведение двух разных подходов соответственно.

Будет ли не кэшированный подход использовать дыру в жестком диске?!

EDIT

Я ушел, чувствуя себя умно во время своего тестирования, а затем использовал кеширующее поведение FileInfo в моей службе Windows (в основном, чтобы сидеть в цикле и говорить «Has-file-change-has-file-Change ...» перед тем, как занимаюсь обработкой)

Хотя этот подход работал на моем устройстве разработки, он не работал в производственной среде, то есть процесс просто продолжал выполняться независимо от того, изменился файл или нет. Я закончил тем, что изменил свой подход к проверке и только использовал GetLastAccessTime как часть этого. Не знаю, почему на рабочем сервере он будет вести себя по-другому ... но я не слишком обеспокоен этим вопросом.

...