Определить чтение файла в C # - PullRequest
8 голосов
/ 01 сентября 2010

Я использую FileSystemWatcher, чтобы проверить, когда файл изменен или удален, но мне интересно, есть ли способ проверить, когда файл читается другим приложением.файл C: \ test.txt на моем жестком диске, и я смотрю его с помощью FileSystemWatcher.Другая программа (не под моим контролем) отправляется на чтение этого файла;Я хотел бы перехватить это событие и, если возможно, проверить, какая программа читает файл, а затем соответствующим образом изменить его содержимое.

Ответы [ 6 ]

4 голосов
/ 02 сентября 2010

Звучит так, будто вы хотите записать в свой файл журнала, когда ваш файл журнала читается извне, или что-то в этом роде.Если это так, существует значение NotifyFilters, LastAccess.Убедитесь, что это установлено в качестве одного из флагов в вашем свойстве FileSystemWatcher.NotifyFilter.Изменение последнего времени доступа затем вызовет событие Changed в FileSystemWatcher.

В настоящее время FileSystemWatcher не позволяет напрямую различать чтение и изменение;они оба запускают событие Changed на основании «изменения» на LastAccess.Таким образом, было бы невозможно следить за чтением большого количества файлов.Однако вы, похоже, знаете, какой файл вы просматриваете, поэтому, если у вас есть объект FileInfo для этого файла и FileSystemWatcher сгенерировал событие Changed, вы можете получить новое и сравнить значения LastAccessTime.Если время доступа изменилось, а LastWriteTime - нет, ваш файл только читается.

Теперь, проще говоря, изменения, внесенные в файл во время чтения, не будут сразу отображаться вдругое приложение, и при этом вы не сможете «добраться первым», заблокировать файл и записать его до того, как они его увидят.Таким образом, вы не можете использовать FileSystemWatcher для «перехвата» запроса на чтение и показа контента, который вы хотите видеть в этом приложении.Пользователь другого приложения может увидеть только что написанное, если приложение также просматривает файл и перезагружает файл.Это вызовет другое событие Changed, вызывая бесконечный цикл, пока другое приложение продолжает перезагружать файл.

Вы также получите событие Changed для чтения и записи.Открытие файла в текстовом редакторе (практически любой подойдет), внесение некоторых изменений, а затем сохранение вызовут два события Changed, если вы ищете изменения в Last Access Time.Первый отключится, когда файл откроется редактором;в то время вы, возможно, не сможете сказать, что произойдет запись, поэтому, если вы ищете доступ к файлу только для чтения, тогда вы SOL.

2 голосов
/ 02 сентября 2010

Есть программа SysInternals FileMon ... Она может отслеживать любой доступ к файлам в системе. Если вы можете найти его источник и понять, какие win32-хуки он использует, вы можете упорядочить эти функции в C # и получить то, что вам нужно.

2 голосов
/ 02 сентября 2010

Самый простой способ сделать это - использовать таймер (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);
}
}
1 голос
/ 02 сентября 2010

Вы можете использовать FileInfo.LastAccessTime и FileInfo.Refresh () в цикле опроса.

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

0 голосов
/ 02 сентября 2010

Да, используя драйвер фильтра файловой системы, вы можете перехватывать все запросы на чтение, анализировать их и даже заменять читаемые данные. Разработка такого драйвера самостоятельно возможна, но очень трудоемка и сложна. Мы предлагаем продукт под названием CallbackFilter , который включает готовый драйвер и позволяет реализовать бизнес-логику фильтрации в пользовательском режиме.

0 голосов
/ 02 сентября 2010

Небольшой фрагмент , который я нашел полезным для обнаружения блокировки другого процесса:

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