检测C#中的文件读取

我正在使用FileSystemWatcher检查文件何时被修改或删除,但我想知道是否有任何方法可以检查其他应用程序何时读取文件。

示例:我的硬盘驱动器上有文件C:\ test.txt,正在使用FileSystemWatcher查看它。 另一个程序(不在我的控制之下)去读取该文件; 我想抓住该事件,如果可能的话,检查正在读取文件的程序,然后相应地修改文件的内容。

听起来你想在外部读取日志文件时写入日志文件,或者是那种效果。 如果是这种情况,则存在NotifyFilters值LastAccess。 确保将其设置为FileSystemWatcher.NotifyFilter属性中的标志之一。 然后,上次访问时间的更改将触发FileSystemWatcher上的Changed事件。

目前,FileSystemWatcher不允许您直接区分读取和更改; 他们都根据LastAccess的“更改”触发Changed事件。 因此,观察对大量文件的读取是不可行的。 但是,您似乎知道您正在查看哪个文件,因此如果您有该文件的FileInfo对象,并且FileSystemWatcher触发了其Changed事件,您可以获得一个新文件并比较LastAccessTime值。 如果访问时间发生更改,而LastWriteTime没有更改,则仅读取您的文件。

现在,简单来说,在读取文件时对文件所做的更改不会立即显示在另一个应用程序中,您也无法“先到达”,锁定文件并写入文件在他们看到之前。 因此,您无法使用FileSystemWatcher“拦截”读取请求并显示您希望该应用程序查看的内容。 另一个应用程序的用户可以看到您刚才写的内容的唯一方法是应用程序是否也在观看文件并重新加载文件。 这将触发另一个Changed事件,只要另一个应用程序继续重新加载文件,就会导致无限循环。

您还将获得读取和写入的Changed事件。 在文本编辑器中打开文件(几乎任何可以做的),进行一些更改,然后保存将触发两个Changed事件,如果您正在寻找对上次访问时间的更改。 第一个将在编辑器打开文件时关闭; 那时,您可能无法判断是否会发生写入,因此如果您正在寻找对该文件的纯只读访问,那么您就是SOL。

我能想到的最简单的方法是使用一个定时器(System.Threading.Timer),它的回调检查并存储最后一个

System.IO.File.GetLastAccessTime(path) 

喜欢的东西(可能有点锁定……)

 public class FileAccessWatcher { public Dictionary _trackedFiles = new Dictionary(); private Timer _timer; public event EventHandler> 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(pair.Key)); } } _timer.Change(500, Timeout.Infinite); } } 

有SysInternals的程序FileMon …它可以跟踪系统中的每个文件访问。 如果您可以找到它的源代码,并了解它使用的win32钩子,您可以在C#中封送这些函数并获得您想要的内容。

您可以在轮询循环中使用FileInfo.LastAccessTime和FileInfo.Refresh()。

http://msdn.microsoft.com/en-us/library/system.io.fileinfo_members.aspx

是的,使用文件系统filter驱动程序,您可以捕获所有读取请求,分析它们甚至替换正在读取的数据。 自己开发这样的驱动程序是可能的,但非常耗时和复杂。 我们提供了一个名为CallbackFilter的产品,它包含一个随时可用的驱动程序,并允许您在用户模式下实现过滤业务逻辑。

我发现一个小片段可用于检测另一个进程何时有锁:

  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; }