Подтвердить что ты не робот

.NET FileInfo.LastWriteTime & FileInfo.LastAccessTime ошибочны

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

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

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

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

Изменить 2: Никто не считает интересным, что эта функция не работает?

4b9b3361

Ответ 1

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

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

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

t = File.GetLastAccessTime(path);

Ответ 2

Из MSDN:

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

FileSystemInfo.Refresh()

Если вы используете приложение, которое делает запись, я думаю, вам придется "прикоснуться" к файлу, установив свойство LastWriteTime самостоятельно между каждым буфером данных, которые вы пишете. Некоторые psuedocode:

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

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

Ответ 3

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

Ответ 4

Начиная с 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

Ответ 5

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

Ответ 6

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

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

Если приложение реализует нечто вроде скользящего регистратора, который закрывает файл, а затем переименовывает его в другое имя файла, вы также сталкиваетесь с проблемами, поскольку время создания и размер файла "старого" файла запоминаются ОС, хотя вы создали новый файл. Это включает неправильные отчеты о размере файла, даже если вы повторно создали log.txt с нуля, размер которого по-прежнему равен 0 байтам. Эта функция называется OS File System Tunneling, которая все еще присутствует в Windows 8.1. Пример того, как реализовать эту проблему, проверьте RollingFlatFileTracelistener из Enterprise Library (http://home.elka.pw.edu.pl/~mrudnik/CREAM/Logging/Src/Logging/TraceListeners/RollingFlatFileTraceListener.cs).

Вы можете увидеть эффекты туннелирования файловой системы на вашей собственной машине из командной оболочки 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

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

Ответ 7

Ответ Tommy Carlier заставил меня думать...

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

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

и

FileInfo bob = new FileInfo(path);

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

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

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

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

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

ИЗМЕНИТЬ

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

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