Установка времени последнего изменения каталога, открытого для ReadDirectoryChangesW
-
16-09-2019 - |
Вопрос
У меня есть Java-программа, которой необходимо отслеживать дерево каталогов на предмет изменений.У меня есть код JNI, который использует ReadDirectoryChangesW()
.Каталог открывается следующим образом:
HANDLE dirHandle = CreateFile(
path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);
и тогда я прохожу мимо dirHandle
Для ReadDirectoryChangesW()
.Все это работает просто отлично.
Проблема в том, что другие части кода (на стороне Java) используют File.setLastModified()
чтобы "прикоснуться" к файлам или каталогам (обновите их временные метки, чтобы они были "сейчас").Обычно это работает;однако при попытке "коснуться" каталога, который был открыт с помощью CreateFile()
.
Чтобы узнать, какая ошибка Windows на самом деле возникает, я просмотрел исходный код JDK для File.setLastModified()
и переопределил это в моем собственном коде с добавлением вывода ошибки из GetLastError()
;ошибка заключается в:
ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."
ВТФ?Это тот самый то же самое процесс.Я даже прошел мимо FILE_SHARE_READ
и FILE_SHARE_WRITE
Для CreateFile()
.
Есть ли способ заставить это работать?
Подробная информация
Реализация в машинном коде File.setLastModified()
в JDK выполняется:
h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
Если я изменю первый 0
Для FILE_SHARE_READ | FILE_SHARE_WRITE
, все это работает.Таким образом, кажется, что реализация JDK немного нарушена.:(
Итак, теперь мой вопрос становится:Есть ли способ заставить это работать без необходимости использовать мою собственную (повторную) реализацию File.setLastModified()
?
Решение
Хотя сообщение об ошибке в данном случае немного вводит в заблуждение, то, что вы видите, является нормальным поведением.
Открыв каталог с помощью dwShareMode
при равном нулю JDK, по сути, запрашивает эксклюзивный доступ, что приведет к сбою любой другой попытки доступа с ошибкой нарушения общего доступа.Это в равной степени относится к доступам
как из других процессов, так и из вашего собственного процесса.
Тот Самый CreateFile
Документация описывает dwShareMode
параметр:
Если этот параметр равен нулю и CreateFile выполняется успешно, файл или устройство не могут быть доступны для общего доступа и не могут быть открыты снова до тех пор, пока не будет закрыт дескриптор файла или устройства.
Вы не можете запросить режим общего доступа, который конфликтует с режимом доступа, указанным в существующем запросе с открытым дескриптором.
CreateFile
потерпел бы неудачу, иGetLastError
функция вернетERROR_SHARING_VIOLATION
.
Итак, похоже, вы сами ответили на свой вопрос:вам нужен индивидуальный подход setLastModified
функция, которая определяет FILE_SHARE_READ | FILE_SHARE_WRITE
при обращении к каталогу.