2013-02-08 116 views
6

我瀏覽過但找不到任何有關我正在尋找的信息,如果有另一篇文章已經過去,那麼我表示歉意。FileSystemWatcher用於監視文件夾/文件打開

我在尋找關於監視特定文件夾的代碼的幫助,該特定文件夾用於何時該文件夾被另一個人打開或當該文件夾下的文件被打開時。此時,我可以看到用戶何時打開和修改任何文件,但是如果他們只是打開文件來查看它,即使添加LastAccessed也不會拋出事件。任何信息或幫助將不勝感激。

文件夾名稱是C:\垃圾

代碼在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

如果文件夾名稱是C:\ JUNK,爲什麼不把它放在Path屬性中? Filter屬性用於屏幕文件不是文件夾 – Steve 2013-02-08 19:12:48

+0

@Steve - 根據你的建議,我改變了我的代碼,但它仍然沒有觸發打開文件夾。 – Saren 2013-02-08 19:15:39

+1

嘗試使用文件系統篩選器驅動程序來跟蹤這種更改。其他變體不能很​​好地工作。 – 2013-02-09 08:07:01

回答

0

您應該設置

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

和刪除watcher.Filter行,如果事件應該解僱所有文件

使用Filter屬性,您可以爲matchi設置通配符ng文件,例如*.txt

+0

我已經改變了我的代碼建議,但仍然沒有觸發開放。 – Saren 2013-02-08 19:16:02

2

即使添加LastAccessed,它也不會拋出事件。

因爲NotifyFilters.LastAccessed指定您希望檢索該屬性,而不是要訂閱的事件。可用的事件是ChangedCreatedDeleted,其中沒有一個是您想要的。

你應該看看ReadDirectoryChangesW Win32函數,記錄在here。它可以通過一個FILE_NOTIFY_CHANGE_LAST_ACCESS標誌,這似乎提供你想要的東西:

任何變化在看着目錄或樹文件的最後訪問時間引起變化通知給等待操作返回。

編輯:忽略這一點,並FileSystemWatcher內部傳遞NotifyFilters.LastWrite爲INT 32,其是相同的FILE_NOTIFY_CHANGE_LAST_ACCESS,到ReadDirectoryChangesW。該功能,然後仍然不通知文件訪問,我試過了。

也許這是由this造成的:

上次訪問時間有一個寬鬆的粒度,只有保證了時間精確到一個小時之內。在Windows Vista中,我們已禁用了上次訪問時間的更新以提高NTFS性能。如果您使用的是依賴於該值的應用程序,你可以使用下面的命令啓用它:

fsutil behavior set disablelastaccess 0 

您必須重新啓動計算機使更改生效。

如果在命令提示符下執行該操作,則可能會寫入LastAccess並且該事件將觸發。我不會嘗試使用我的SSD,並且沒有準備好虛擬機,但在Windows 7上disablelastaccess似乎是開箱即用的。

如果在禁用該行爲時仍不起作用,請等待Raymond Chen的建議框(或自己)過來,通常有一個非常合理的解釋,爲什麼文檔似乎沒有正確描述您的行爲遭遇。 ;-)

你也可以在循環中掃描目錄並查看文件的LastAccessed屬性。你想做什麼用戶打開某個文件?

+0

非常感謝! – Saren 2013-02-08 19:27:11

+0

首先嚐試實施它;;) – CodeCaster 2013-02-08 19:27:39

+0

它似乎是一個PITA,但這是另一次,現在我很高興我有一個路線。 – Saren 2013-02-08 19:28:30

0

你真正需要的是NtQuerySystemInformation枚舉和一個計時器,這樣你可以掃描目錄,看看是否有任何文件是打開的。文件系統監視器不會給你這個信息

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

要獲得On-Access文件路徑,有一個小型過濾器驅動程序的解決方案。您必須實施小型過濾器驅動程序才能實施要求。