2013-02-08 17 views
6

Ho cercato, ma non riesco a trovare alcuna informazione su quello che sto cercando, se c'è un altro post che già va oltre questo allora mi scuso.FileSystemWatcher utilizzato per la visualizzazione di cartella/file aperti

Sono in cerca di aiuto con il codice che monitorerà una cartella specifica per quando la cartella viene aperta da un'altra persona o quando viene aperto un file sotto detta cartella. A questo punto posso vedere quando un utente apre e modifica qualsiasi file, ma se solo aprono il file per vederlo, non lancia un evento nemmeno quando aggiungo LastAccessed. Qualsiasi informazione o aiuto sarebbe apprezzato.

nome della cartella è C: \ Junk

codice in C# 4.0:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
    public static void Run() 
    { 


     FileSystemWatcher watcher = new FileSystemWatcher(); 
     watcher.Path = @"C:\"; 
     watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite 
      | NotifyFilters.FileName | NotifyFilters.DirectoryName; 
     watcher.Filter = "junk"; 

     // Add event handlers. 
     watcher.Changed += new FileSystemEventHandler(OnChanged); 
     watcher.Created += new FileSystemEventHandler(OnChanged); 
     watcher.Deleted += new FileSystemEventHandler(OnChanged); 
     watcher.Renamed += new RenamedEventHandler(OnRenamed); 
     watcher.IncludeSubdirectories = true; 
     watcher.EnableRaisingEvents = true; 

     // Wait for the user to quit the program. 
     Console.WriteLine("Press \'q\' to quit the sample."); 
     while (Console.Read() != 'q') ; 
    } 

    // Define the event handlers. 
    private static void OnChanged(object source, FileSystemEventArgs e) 
    { 
     // Specify what is done when a file is changed, created, or deleted. 
     Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType); 
    } 

    private static void OnRenamed(object source, RenamedEventArgs e) 
    { 
     // Specify what is done when a file is renamed. 
     Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath); 
    } 
+0

Se il nome della cartella è C: \ JUNK, perché non lo si inserisce nella proprietà Path? la proprietà Filter viene utilizzata per lo screening di file e non cartelle – Steve

+0

@Steve - Per il tuo suggerimento, ho cambiato il mio codice ma non si attiva ancora all'apertura della cartella. – Saren

+1

Prova il driver del filtro del filesystem per tracciare questo tipo di modifiche. Altre varianti non funzionano bene. –

risposta

0

È necessario impostare

watcher.Path = @"C:\junk"; 

ed eliminare watcher.Filter linea se l'evento dovrebbe fuoco per tutti i file

Utilizzando la proprietà Filter è possibile impostare i caratteri jolly per matchi file ng, ad esempio *.txt

+0

Ho cambiato il mio codice come suggerito ma ancora nessun trigger aperto. – Saren

2

non lancia un evento anche quando aggiungo LastAccessed.

Perché NotifyFilters.LastAccessed specifica che si desidera recuperare tale proprietà, non l'evento a cui iscriversi. Gli eventi disponibili sono Changed, Created o Deleted, nessuno dei quali fa quello che vuoi.

Si dovrebbe dare un'occhiata alla funzione Win32 ReadDirectoryChangesW, documentata here. Può essere passato una bandiera FILE_NOTIFY_CHANGE_LAST_ACCESS, che sembra fornire ciò che si vuole:

Qualsiasi modifica l'ultima volta che l'accesso del file nella directory visto o sottostruttura impedisce l'operazione di cambiamento di notifica ora di tornare.

Edit: ignorare questo, il FileSystemWatcher fa passare internamente NotifyFilters.LastWrite come int 32, che è lo stesso come FILE_NOTIFY_CHANGE_LAST_ACCESS, a ReadDirectoryChangesW. Quella funzione quindi non notifica ancora l'accesso ai file, ci ho provato.

Forse questo è causato da this:

ultimo accesso tempo ha una granularità sciolto che garantisce solo che il tempo è una precisione di un'ora. In Windows Vista, abbiamo disattivato gli aggiornamenti di Last Access Time per migliorare le prestazioni NTFS. Se si utilizza un'applicazione che si basa su questo valore, è possibile attivare utilizzando il seguente comando:

fsutil behavior set disablelastaccess 0 

È necessario riavviare il computer affinché questa modifica abbia effetto.

Se lo si esegue al prompt dei comandi, forse lo LastAccess verrà scritto e l'evento verrà generato.Non ho intenzione di provare sul mio SSD e non ho una VM pronta, ma su Windows 7 disablelastaccess sembra essere abilitato subito.

Se ancora non funziona quando si disabilita tale comportamento, attendere che arrivi la finestra di suggerimento di Raymond Chen (o se stesso), di solito c'è una spiegazione abbastanza logica del perché la documentazione non sembra descrivere correttamente il comportamento incontrare. ;-)

Si può anche solo eseguire la scansione della directory in un ciclo e osservare la proprietà LastAccessed dei file. Cosa stai cercando di fare quando un utente apre un determinato file?

+0

Grazie mille! – Saren

+0

Primo tentativo di implementarlo ...;) – CodeCaster

+0

Sembra essere un PITA ma questo è per un'altra volta, per ora sono felice di avere una strada da percorrere. – Saren

0

ciò di cui hai veramente bisogno è l'enumerazione NtQuerySystemInformation e un timer, in questo modo è possibile eseguire la scansione della directory e vedere se uno qualsiasi dei file è aperto. il filesystemwatcher non ti darà queste informazioni

0
public void OnChanged(object sender, FileSystemEventArgs e) 
{ 
    string FileName = System.IO.Path.GetFileName(e.FullPath); 

    if(IsAvailable(System.IO.Path.Combine(RecievedPath,FileName))) 
    { 
     ProcessMessage(FileName); 
    } 
} 


private void ProcessMessage(string fileName) 
{ 
    try 
    { 
     File.Copy(System.IO.Path.Combine(RecievedPath,fileName), System.IO.Path.Combine(SentPath,fileName)); 
     MessageBox.Show("File Copied"); 
    } 
    catch (Exception) 
    { } 
} 

private static bool IsAvailable(String filePath) 
{ 
    try 
    { 
     using (FileStream inputStream = File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.None)) 
     { 
      if (inputStream.Length > 0) 
      { 
       return true; 
      } 
      else 
      { 
       return false; 
      } 

     } 
    } 
    catch (Exception) 
    { 
     return false; 
    } 
} 
0

Per ottenere il percorso del file in accesso c'è una soluzione del driver del minifiltro. Devi implementare il driver del minifiltro per ottenere i requisiti implementati.

Problemi correlati