2012-12-26 16 views
16

cerco di capire ReadDirectoryChangesW funzione in modo da poter essere informato in modo efficace sul cambiamento di contenuti in diverse directory (file sovrascritti, file cancellati, rinominati, ecc ..).C++ Winapi: ReadDirectoryChangesW() Ricezione doppie Notifiche

Uno dei miei recenti osservazioni è che per ogni file operazione di scrittura, ricevo sempre due notifiche per singolo file.

Ho tracciato con molta attenzione, e sono sicuro, che se sovrascrivo un file (ad esempio un file .txt con un nuovo contenuto - fondamentalmente un paio di lettere extra all'interno), ReadDirectoryChangesW() mi notifica due volte per quel file salvato.

Questa è una cosa seria, poiché mi aspetto di ricevere una notifica solo una volta per ogni modifica. Non desidero ripetere involontariamente operazioni che dovrebbero accadere solo una volta nella mia applicazione.

È noto questo comportamento? C'è un modo per ricevere solo una notifica per una modifica, per favore? C'è modo di efficacemente evitare doppie notifiche?

io uso:

  • non gestito C++
  • Visual Studio 2012
  • Windows 7 x64

io uso il codice piuttosto semplice per fare le mie prove, ma si vuole vedere esso, quindi eccolo:

HANDLE hDir = CreateFile(
    lpDir, 
    FILE_LIST_DIRECTORY, 
    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_FLAG_BACKUP_SEMANTICS, 
    NULL); 

    int nCounter = 0; 
    FILE_NOTIFY_INFORMATION strFileNotifyInfo[1024]; 
    DWORD dwBytesReturned = 0; 

    while(TRUE) 
    { 
     if(ReadDirectoryChangesW (hDir, (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytesReturned, NULL, NULL) == 0) 
     { 
      ErrorCheck(_T("Reading Directory Change")); 
     } 
     else 
     { 
      _tcout << _T("File Modified: ") << strFileNotifyInfo[0].FileName << endl; 
      _tcout << _T("Loop: ") << nCounter++ << endl; 
     } 
    } 
+0

Prima di pronunciare ogni operazione di scrittura, ma il tuo esempio è sovrascritto. Vorrei ipotizzare che la sovrascrittura potrebbe comportare più di una singola operazione dal punto di vista della directory (come eliminare quindi creare) anziché solo scrivere/accodare a un file esistente. Ma non ho alcun riferimento autorevole su questo ... – TheUndeadFish

+0

possibile duplicato di [voci doppie di Filesystemwatcher] (http://stackoverflow.com/questions/9902758/filesystemwatcher-double-entries) –

+0

@TheUndeadFish, ciao e grazie per la tua idea. È davvero molto intelligente. Ho provato i miei test con altre bandiere. Posso dire che, ad esempio, ** FILE_NOTIFY_CHANGE_ATTRIBUTES ** restituisce anche due notifiche. Questo può essere spiegato, che su sovrascrittura di file, più di un attributo è normalmente cambiato? –

risposta

18

ReadDirectoryChangesW() presenta una visione molto miope del file system. Vede ogni cambia nel file system e li segnala diligentemente. E sì, c'è spesso più di uno quando scrivi su un file. È un dettaglio di implementazione del particolare file system che si sta utilizzando, ma qualsiasi comune in Windows mantiene anche una voce di directory per un file che memorizza i metadati per il file.

Quindi si vede la scrittura per i dati del file. Ma è anche vedere cambiare la voce di directory. In particolare la dimensione del file, è probabile che cambi quando scrivi un file e aggiungi dati al file. E i timestamp di ultima scrittura e ultimo accesso registrati nella voce della directory. L'api è altrimenti cieca al tipo di cambiamento che viene fatto, vede solo la scrittura di basso livello. Inoltre è completamente inconsapevole di quale particolare processo ha richiesto la scrittura.

Questo è qualcosa che dovrete affrontare, non c'è modo di distinguere queste scritture. Tutto quello che sai è "il file è stato cambiato". Come, perché, da chi e quanto spesso è del tutto inafferrabile.

Un'altra cosa che dovrete affrontare è che, nel momento in cui viene generata la notifica, il processo che scrive il file è molto probabile che abbia ancora un blocco sul file. Che ti impedisce di fare qualcosa di utile con il file te stesso. Come leggere il file o copiarlo è probabile che fallisca. È necessario attendere fino a quando il processo è terminato con il file e ha chiuso l'handle al file. Non c'è modo di scoprirlo, se non tentando di aprire il file da solo e negare qualsiasi condivisione. Ciò richiede un timer, che tenta di acquisire periodicamente un blocco sul file. Una volta ottenuto l'impianto idraulico, non è più necessario ricevere più di una notifica di modifica per il file.

+2

+1 e grazie per la risposta. L'hai spiegato in modo molto carino, con l'idea proposta di soluzione. Implementerò il monitoraggio basato sul timer. Le tue risposte e quelle di Sergmat sono entrambe molto buone. È difficile decidere quale contrassegnare come * Risposta accettata *, ma, fornendo ulteriori informazioni, sto segnalando la tua risposta. Grazie ancora. –

6

Questa è l'operazione di risultato del codice in esecuzione contemporaneamente alla registrazione procmon dopo il salvataggio del file nel blocco note. Ci sono due notifiche da ReadDirectoryChangesW() e due notifiche da procmon. 2 IRP_MJ_WRITE 1 dal blocco note (WriteFile) 1 dal Sistema Gestione cache (CcWriteBehind) procmon

+0

Questo sembra ragionevole ma non sono sicuro ... la documentazione di 'FILE_NOTIFY_CHANGE_LAST_WRITE' su http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx "Qualsiasi modifica all'ultimo tempo di scrittura dei file nella directory o sottostruttura guardata causa il ritorno di una notifica di notifica. * Il sistema operativo rileva una modifica all'ultimo tempo di scrittura solo quando il file viene scritto sul disco * Per i sistemi operativi che utilizzano la memorizzazione nella cache estesa, il rilevamento si verifica solo quando la cache viene sufficientemente svuotata. " –

+0

@sergmat: +1 halo e grazie per la spiegazione. La tua analisi è ottima e spiega perfettamente questo problema. Mi dispiace, non sono riuscito a trovare una risposta da solo. Sembra che Process Monitor di Sysinternals.com sia uno strumento molto potente. –

+0

@NikBougalis, ciao Nik, sì, ho letto quel paragrafo dalla documentazione. Sembra che Sergmat abbia spiegato questo, e dovrò monitorare tutte le notifiche in base al tempo trascorso, quindi eviterò quelle doppie. –

Problemi correlati