2011-08-26 12 views
8

Vorrei eseguire il polling del file system per qualsiasi file, sottodirectory, modificato o aggiunto. Tutte le modifiche dovrebbero essere rilevate rapidamente ma senza esercitare pressione sulla macchina. Il sistema operativo è Windows> = Vista, la parte osservata è una directory locale.Come si esegue il polling di un numero elevato di file per le modifiche?

In genere, ricorrere a un FileSystemWatcher, ma questo ha portato a problemi con altri programmi che hanno cercato di vedere lo stesso punto (in primo piano, Windows Explorer). Inoltre, ho sentito che FSW non è realmente affidabile anche per le cartelle locali e con un buffer di grandi dimensioni.

Il problema principale che ho è che il numero di file e directory può essere molto grande (indovinate 7 cifre). Il semplice fatto di eseguire un controllo di tutti i file ogni secondo ha influito notevolmente sulla mia macchina.

La mia prossima idea era di controllare diverse parti dell'intero albero al secondo per ridurre l'impatto complessivo, e magari aggiungere una sorta di euristica, come controllare i file che vengono cambiati frequentemente in una più rapida successione.

Mi chiedo se ci sono schemi per questo tipo di problema, o se qualcuno ha esperienze con questa situazione.

+0

Tutte le sottocartelle sono sotto una singola radice? Che tipo di problemi hai avuto con Windows Explorer? Ecco uno schema per assicurarti di non perdere nessun messaggio. http://stackoverflow.com/questions/4967095/c-predict-file-system-events-on-folder-delete/4968391#4968391 – adrianm

+0

@adrianm: Sì, stessa radice. --- Explorer non ha aggiornato la sua vista quando è stata cambiata una cartella monitorata, suppongo perché FSW ha rubato i suoi eventi. – mafu

risposta

3

Abbiamo implementato una funzionalità simile, utilizzando C#. FileSystemWatcher era inefficiente con grandi alberi di directory.

La nostra alternativa, stava usando FSNodes, una struct creata da noi, utilizzando le seguenti chiamate API di Windows:

[StructLayout(LayoutKind.Sequential)] 
     private struct FILETIME 
    { 
     public uint dwLowDateTime; 
     public uint dwHighDateTime; 
    }; 

    [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] 
     private struct WIN32_FIND_DATA 
    { 
     public FileAttributes dwFileAttributes; 
     public FILETIME ftCreationTime; 
     public FILETIME ftLastAccessTime; 
     public FILETIME ftLastWriteTime; 
     public uint nFileSizeHigh; 
     public uint nFileSizeLow; 
     public int dwReserved0; 
     public int dwReserved1; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_PATH)] 
     public string cFileName; 
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst=MAX_ALTERNATE)] 
     public string cAlternate; 
    } 

    [DllImport("kernel32.dll", SetLastError = true)] 
    static extern bool FindClose(IntPtr hFindFile); 

    [DllImport("kernel32", CharSet=CharSet.Unicode)] 
    private static extern IntPtr FindFirstFile(
     string lpFileName, out WIN32_FIND_DATA lpFindFileData); 

    [DllImport("kernel32", CharSet=CharSet.Unicode)] 
    private static extern bool FindNextFile(
     IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData); 

Quello che facciamo è un'elaborazione statica. Salviamo un albero di metadati sul disco e confrontiamo l'albero della directory memorizzato con quello caricato, cercando modificato (basato sul suo timestamp (più veloce) o sull'hash del file). Inoltre, possiamo gestire cancellati, aggiunti e spostati, anche i file modificati con mosse (anche in base all'hash del file).

Questa implementazione combinata con un demone che l'ha eseguita ogni POLL_TIME, era valida per noi. Spero che sia d'aiuto.

+0

Potresti spiegare come stai usando le chiamate API Win32? – Cocowalla

+0

'FindFirstFile' cerca una directory per un file o una sottodirectory con un nome che corrisponde a un nome specifico (o un nome parziale se vengono utilizzati i caratteri jolly). 'FindNextFile' continua una ricerca di file da una precedente chiamata alla funzione' FindFirstFile' o 'FindFirstFileEx'. Chiude un handle di ricerca file aperto dalle funzioni 'FindFirstFile' (e altre). Raccomando una ricerca su google per migliorare l'API. –

0

Per ambienti * nix è possibile utilizzare inotify https://github.com/rvoicilas/inotify-tools/wiki/, che ha funzionato benissimo nella mia limitata ricerca su di esso. Ci potrebbe essere una versione là fuori che funziona con Windows che ho meno esperienza con ... googling veloce mi ha portato a un clone java chiamato jnotify http://jnotify.sourceforge.net/ che è pubblicizzato per funzionare su Windows quindi potrebbe valere la pena provare.

1

La mia ipotesi migliore sarebbe quella di utilizzare il journal USN se si tratta di un computer locale, i privilegi di amministratore e le partizioni sono NTFS. Il diario USN è estremamente veloce e affidabile. È un lungo topis e questo link spiega tutto: http://www.microsoft.com/msj/0999/journal/journal.aspx

Problemi correlati