2010-09-01 138 views
8

我正在使用FileSystemWatcher來檢查文件被修改或刪除的時間,但我想知道是否有任何方法來檢查另一個應用程序讀取文件的時間。在C中讀取文件讀取#

例如: 我在我的硬盤上有C:\ test.txt文件,並正在使用FileSystemWatcher進行觀察。另一個程序(不在我的控制下)去閱讀該文件;我想捕捉該事件,並且如果可能的話,檢查哪個程序正在讀取該文件,然後相應地修改該文件的內容。

+1

這似乎是一個奇怪的要求。你能擴展你的最終目標是多一點嗎? – luke 2010-09-01 20:35:10

+0

@luke - 我想要做的是加密文件的一部分,但是當一個web應用程序(我沒有控制權)讀取該文件時,我將解密它的加密部分。 – 2010-09-02 15:27:38

+0

它似乎是一個更好的解決方法,只需要設置更細粒度的訪問控制,以便只有Web應用程序(和您的應用程序)才能讀取文件,那麼您根本不需要加密它。 – luke 2010-09-02 15:30:32

回答

4

聽起來好像你想寫日誌文件的時候你的日誌文件是從外部讀取的,或者是這個效果。如果是這種情況,則有一個NotifyFilters值LastAccess。確保它被設置爲FileSystemWatcher.NotifyFilter屬性中的一個標誌。上次訪問時間的更改將觸發FileSystemWatcher上的Changed事件。

目前,FileSystemWatcher不允許您直接區分讀取和更改;他們都會根據「更改」觸發Changed事件到LastAccess。因此,觀察讀取大量文件是不可行的。但是,您似乎知道您正在監視哪個文件,因此如果您有該文件的FileInfo對象,並且FileSystemWatcher觸發了其更改事件,則可以獲取新文件並比較LastAccessTime值。如果訪問時間改變,並且LastWriteTime沒有,你的文件只被讀取。

現在,用最簡單的術語來說,在讀取文件時對文件所做的更改不會立即顯示在另一個應用程序中,也不能夠「先到達」,鎖定文件並在他們看到之前寫信給它。因此,您無法使用FileSystemWatcher「截取」讀取請求並顯示您希望應用程序查看的內容。另一個應用程序的用戶可以看到你剛剛寫的內容的唯一方法就是該應用程序還在觀看該文件並重新加載該文件。這將觸發另一個Changed事件,只要其他應用程序繼續重新加載文件,就會導致無限循環。

您還將獲得讀取和寫入的Changed事件。在文本編輯器中打開一個文件(實際上會做任何操作),進行一些更改,然後如果您正在查找上次訪問時間的更改,保存將觸發兩個更改的事件。當編輯打開文件時,第一個文件將會關閉;那時候,你可能無法知道寫入會發生,所以如果你正在尋找對文件的純粹只讀訪問,那麼你就是SOL。

-2

snippet,我發現有用,當另一個進程有一個鎖定檢測:

static bool IsFileUsedbyAnotherProcess(string filename) 
     { 
      try 
      { 
       using(var file = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.None)) 
       { 
       } 
      } 
      catch (System.IO.IOException exp) 
      { 
       return true; 
      } 
      return false; 
     } 
+3

只有在其他應用程序已將其鎖定寫入時纔有效。打開要讀取的文件並不一定會將其鎖定。 – KeithS 2010-09-01 20:08:03

+3

Egad!該功能將文件保持打開狀態,直到它被垃圾收集,這意味着沒有其他人可以在未啓用共享的情況下打開它。 – Gabe 2010-09-01 20:11:38

+2

誰在這裏關閉File.Open()? – kofucii 2010-09-01 20:12:23

2

最簡單的方法是用一個計時器(System.Threading.Timer),其回調的檢查和存儲最後

System.IO.File.GetLastAccessTime(path) 

喜歡的東西(可能與更多的鎖定...)

public class FileAccessWatcher 
{ 

public Dictionary<string, DateTime> _trackedFiles = new Dictionary<string, DateTime>(); 

private Timer _timer; 

public event EventHandler<EventArgs<string>> FileAccessed = delegate { }; 

public FileAccessWatcher() 
{ 
    _timer = new Timer(OnTimerTick, null, 500, Timeout.Infinite); 
} 

public void Watch(string path) 
{ 
    _trackedFiles[path] = File.GetLastAccessTime(path); 
} 

public void OnTimerTick(object state) 
{ 
    foreach (var pair in _trackedFiles.ToList()) 
    { 
     var accessed = File.GetLastAccessTime(pair.Key); 
     if (pair.Value != accessed) 
     { 
      _trackedFiles[pair.Key] = accessed; 
      FileAccessed(this, new EventArgs<string>(pair.Key)); 
     } 
    } 

    _timer.Change(500, Timeout.Infinite); 
} 
} 
2

有SysInternals的程序FileMon ...它可以跟蹤系統中的每個文件訪問。如果你能找到它的源代碼,並且理解它使用的win32鉤子,你可以用C#編制這些函數並得到你想要的。

0

是的,使用文件系統過濾器驅動程序,您可以捕獲所有讀取請求,分析它們,甚至替代正在讀取的數據。自己開發這種驅動程序是可能的,但非常耗時且複雜。我們提供名爲CallbackFilter的產品,其中包含一個隨時可用的驅動程序,並允許您在用戶模式下實施您的過濾業務邏輯。