Impostazione del dell'ultima modifica in tempo di una directory aperta per ReadDirectoryChangesW
-
16-09-2019 - |
Domanda
I hava un programma Java che ha bisogno di monitorare un albero di directory per i cambiamenti. Ho codice JNI che utilizza ReadDirectoryChangesW()
. La directory viene aperta come:
HANDLE dirHandle = CreateFile(
path, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL
);
e poi mi passa dirHandle
a ReadDirectoryChangesW()
. Tutto questo funziona bene.
Il problema è che altre parti del codice (sul lato Java) usano File.setLastModified()
ai file "touch" o directory (aggiornare i loro timestamp di essere "ora"). Questo funziona in genere; tuttavia, non riesce quando ha cercato di "toccare" la directory che è stato aperto utilizzando CreateFile()
.
Per vedere ciò che di errore di Windows è effettivamente in corso, ho guardato la fonte JDK per File.setLastModified()
e reimplementato nel mio proprio codice con l'aggiunta di stampare l'errore da GetLastError()
; l'errore è:
ERROR_SHARING_VIOLATION (error 32)
"The process cannot access the file because it is being used by another process."
WTF? E 'il stesso processo. Ho anche passato FILE_SHARE_READ
e FILE_SHARE_WRITE
a CreateFile()
.
C'è un modo per fare questo lavoro?
Ulteriori informazioni
L'implementazione del codice nativo del File.setLastModified()
nel JDK fa un:
h = CreateFileW(pathbuf, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0);
Se cambio il primo 0
a FILE_SHARE_READ | FILE_SHARE_WRITE
, tutto funziona. Così sembra che l'attuazione JDK è un po 'rotto. : (
Quindi la mia domanda ora diventa:? C'è un modo per fare questo lavoro senza la necessità di usare la mia (ri) attuazione di File.setLastModified()
Soluzione
Anche se il messaggio di errore è un po 'fuorviante, in questo caso, quello che stai vedendo è un comportamento normale.
Con l'apertura della directory con il set dwShareMode
a zero, il JDK è, in effetti, chiedendo per l'accesso esclusivo, che farà sì che qualsiasi altro tentativo di accesso a fallire con un errore di violazione di condivisione. Ciò vale anche per accessi
da altri processi e da dentro il proprio processo.
Il CreateFile
documentazione descrive il parametro dwShareMode
:
Se questo parametro è zero e CreateFile riesce, il file o il dispositivo non possono essere condivise e non può essere aperto di nuovo fino a quando la maniglia per il file o il dispositivo è chiuso.
Non è possibile richiedere una modalità di condivisione che è in conflitto con la modalità di accesso specificato in una richiesta esistente che ha un handle aperto.
CreateFile
fallirebbe e la funzioneGetLastError
sarebbe tornatoERROR_SHARING_VIOLATION
.
Così, sembra che hai risposto alla tua domanda:. Hai bisogno di una funzione di setLastModified
personalizzata che specifica FILE_SHARE_READ | FILE_SHARE_WRITE
quando si accede alla directory