检测C#中的文件读取

时间:2010-09-01 19:55:54

标签: c# file-io filesystemwatcher

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

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

6 个答案:

答案 0 :(得分:4)

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

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

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

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

答案 1 :(得分: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 :(得分:2)

有SysInternals的程序FileMon ...它可以跟踪系统中的每个文件访问。如果你能找到它的来源,并了解它使用的win32钩子,你可以用C#编组这些函数并得到你想要的。

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:-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; 
        }