Definir a última modificação em tempo de um diretório aberto para ReadDirectoryChangesW
-
16-09-2019 - |
Pergunta
Eu hava um Java programa que precisa para monitorar uma árvore de diretórios para mudanças. Eu tenho o código JNI que usos ReadDirectoryChangesW()
. O diretório é aberto como:
HANDLE dirHandle = CreateFile(
path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);
e então eu passar dirHandle
para ReadDirectoryChangesW()
. Tudo isso funciona muito bem.
O problema é que outras partes do código (no lado do Java) uso File.setLastModified()
para arquivos "toque" ou diretórios (actualizar as suas marcas de tempo para ser "agora"). Isso geralmente funciona; no entanto, ele falha quando tentou "toque" o diretório que foi aberto usando CreateFile()
.
Para ver o erro do Windows está realmente acontecendo, eu olhei para a fonte JDK para File.setLastModified()
e reimplemented-lo em meu próprio código com a adição de imprimir o erro de GetLastError()
; o erro é:
ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."
WTF? É o mesma processo. Eu até passou FILE_SHARE_READ
e FILE_SHARE_WRITE
para CreateFile()
.
Existe uma maneira de fazer este trabalho?
Mais informações
A implementação de código nativo do File.setLastModified()
no JDK faz um:
h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
Se eu mudar o primeiro 0
para FILE_SHARE_READ | FILE_SHARE_WRITE
, tudo funciona. Assim, parece que a implementação JDK é um pouco quebrado. : (
Assim, a minha pergunta agora é:? Existe uma maneira de fazer este trabalho sem ter que usar o meu próprio (re) implantação de File.setLastModified()
Solução
Embora a mensagem de erro é um pouco enganador, neste caso, o que você está vendo é um comportamento normal.
Ao abrir o diretório com o conjunto dwShareMode
a zero, o JDK é, com efeito, pedindo acesso exclusivo, o que fará com que qualquer outra tentativa de acesso a falhar com um erro de violação de compartilhamento. Isso se aplica igualmente aos acessos
de outros processos e de dentro do seu próprio processo.
O CreateFile
documentação descreve o parâmetro dwShareMode
:
Se este parâmetro é zero e CreateFile sucedido, o arquivo ou dispositivo não pode ser compartilhado e não pode ser aberta novamente até que o identificador para o arquivo ou dispositivo está fechado.
Você não pode solicitar um modo de compartilhamento que os conflitos com o modo de acesso que está especificado em um pedido existente que tem um identificador aberto.
CreateFile
iria falhar ea funçãoGetLastError
voltariaERROR_SHARING_VIOLATION
.
Assim, parece que você respondeu a sua própria pergunta:. Você precisa de uma função setLastModified
personalizado que especifica FILE_SHARE_READ | FILE_SHARE_WRITE
ao acessar o diretório