Отслеживание изменений в файловой системе

      Для отслеживания изменений в заданном каталоге можно воспользоваться классом «FileSystemWatcher» из пространства имен System.IO. Данный класс предназначен для отслеживания изменений в файловой системе. Изменения можно отслеживать как на локальном компьютере, так и на удаленном. ОС Windows уведомляет компонент об изменениях файлов в буфере, созданном объектом «FileSystemWatcher». Если в течение короткого времени происходит много изменений, буфер может переполниться. В результате этот компонент не сможет отслеживать изменения в каталоге и будет давать только общие уведомления. Увеличение размера буфера с использованием свойства «InternalBufferSize» сопряжено с большими накладными расходами, поскольку он формируется не в выгружаемой памяти и не может быть подкачан с диска, поэтому буфер следует делать как можно меньше, в то же время он должен быть достаточно большим, чтобы не пропустить какие-либо события, связанные с изменениями файлов. Чтобы устранить переполнение буфера, необходимо использовать свойства «NotifyFilter» и «IncludeSubdirectories» для фильтрации ненужных уведомлений.
      Рассмотрим создание проекта отслеживающего изменения в выбранном пользователем каталоге с настройкой фильтров.

      Создайте проект «Windows Form» в «Microsoft Visual Studio» и добавьте на форму следующие элементы управления:
  • System.Windows.Forms.TextBox textBox1 - Элемент управления для вывода пути к выбранной директории;
  • System.Windows.Forms.TextBox textBox2 - Элемент управления для указания строки фильтра, используемую для определения файлов, контролируемых в каталоге. По умолчанию используется "*.*" (отслеживаются все файлы);
  • System.Windows.Forms.ListBox listBox1 - Элемент управления для вывода событий;
  • System.Windows.Forms.GroupBox ControlGroup - Элемент управления объединяющий элементы управления задающие фильтр, наблюдаемые в файле или папке;
  • System.Windows.Forms.GroupBox NotificationsGroup – Элемент управления объединяющий элементы управления задающие изменения, наблюдаемые в файле или папке;
  • System.Windows.Forms.CheckBox checkBox1 - Элемент управления задающий значение, определяющее, доступен ли данный компонент fileSystemWatcher1;
  • System.Windows.Forms.CheckBox checkBox2 - Элемент управления задающий значение, показывающее необходимость контроля изменения атрибутов файла или каталога;
  • System.Windows.Forms.CheckBox checkBox3 - Элемент управления задающий значение, показывающее необходимость контроля времени создания файла и каталога;
  • System.Windows.Forms.CheckBox checkBox4 - Элемент управления задающий значение, показывающее необходимость контроля изменения имени каталога;
  • System.Windows.Forms.CheckBox checkBox5 - Элемент управления задающий значение, показывающее необходимость контроля изменения имени файла;
  • System.Windows.Forms.CheckBox checkBox6 - Элемент управления задающий значение, показывающее необходимость контроля даты последнего открытия файла или каталога;
  • System.Windows.Forms.CheckBox checkBox7 - Элемент управления задающий значение, показывающее необходимость контроля даты последней записи в файл или папку;
  • System.Windows.Forms.CheckBox checkBox8 - Элемент управления задающий значение, показывающее необходимость контроля изменения параметров безопасности файла или папки;
  • System.Windows.Forms.CheckBox checkBox9 - Элемент управления задающий значение, показывающее необходимость контроля изменения размер файла или папки;
  • System.Windows.Forms.CheckBox checkBox10 – Элемент управления задающий значение, показывающее необходимость контроля вложенных каталогов по указанному пути;
  • System.Windows.Forms.Button button1 - Кнопка открытия диалогового окна для выбора каталога, который будет отслеживать элемент управления fileSystemWatcher1;
  • System.IO.FileSystemWatcher fileSystemWatcher1 – Элемент управления отслеживающий изменения в файловой системе.
У вас получится приведенный ниже пример.
      Сделайте двойной клик левой клавишей мыши по любому свободному месту главной формы, вы перейдете в редактор кода с установкой курсора в автоматически созданном методе «Form1_Load», события «Load», выполняющегося при загрузке формы. Вставьте в тело данного метода приведенный ниже листинг, указания имен методов на определенные события элемента управления «fileSystemWatcher1».
//Задаем объект, используемый для маршалинга вызовов обработчика
//событий, инициированных в результате изменения каталога.
fileSystemWatcher1.SynchronizingObject = this;
//Событие возникающее при изменении файла или каталога в заданном пути.
fileSystemWatcher1.Changed += new FileSystemEventHandler(LogFileSystemChanges);
//Событие возникающее при создании файла или каталога в заданном пути.
fileSystemWatcher1.Created += new FileSystemEventHandler(LogFileSystemChanges);
//Событие возникающее при удалении файла или каталога в заданном пути.
fileSystemWatcher1.Deleted += new FileSystemEventHandler(LogFileSystemChanges);
//Событие возникающее при переименовании файла или каталога в заданном пути.
fileSystemWatcher1.Renamed += new RenamedEventHandler(LogFileSystemRenaming);
//Событие возникающее при переполнении внутреннего буфера.
fileSystemWatcher1.Error += new ErrorEventHandler(LogBufferError);
Так же добавьте приведенные ниже методы в листинг главной формы.
void LogBufferError(object sender, ErrorEventArgs e)
{
    string log = string.Format("{0:G} | Переполнен внутренний буфер", DateTime.Now);
            //Добавляем новую запись события.
            listBox1.Items.Add(log);
            //Выбираем последнюю добавленную запись.
            listBox1.SelectedIndex = listBox1.Items.Count - 1;
}

void LogFileSystemRenaming(object sender, RenamedEventArgs e)
{
    string log = string.Format("{0:G} | {1} | Переименован файл {2}",
        DateTime.Now, e.FullPath, e.OldName);
    //Добавляем новую запись события.
    listBox1.Items.Add(log);
    //Выбираем последнюю добавленную запись.
    listBox1.SelectedIndex = listBox1.Items.Count - 1;
}

void LogFileSystemChanges(object sender, FileSystemEventArgs e)
{
    string log = string.Format("{0:G} | {1} | {2}", DateTime.Now, e.FullPath, e.ChangeType);
    //Добавляем новую запись события.
    listBox1.Items.Add(log);
    //Выбираем последнюю добавленную запись.
    listBox1.SelectedIndex = listBox1.Items.Count - 1;
}
      Перейдите в конструктор главной формы и выполните двойной клик левой клавишей мыши по элементу управления «button1», вы перейдете в редактор кода с установкой курсора в автоматически созданном методе «button1_Click», события «Click», выполняющегося при клике по данному элементу управления. Вставьте в тело данного метода приведенный ниже листинг вывода окна выбора директории для отслеживания.
//Создание класса для вывода окна выбора директории
FolderBrowserDialog fbd = new FolderBrowserDialog();

//Выводим диалоговое окно для выбора каталога.
// Данный класс возвращает следующие значения:
// 1) Объект System.Windows.Forms.DialogResult.OK, 
//    если пользователь нажимает кнопку 
//    ОК в диалоговом окне;
// 2) Объект System.Windows.Forms.DialogResult.Cancel,  
//    если пользователь закрывает диалоговое окно.
DialogResult result = fbd.ShowDialog();

//Если пользователь выбрал директорию
//и нажал ОК, то выводим путь в textBox1
if (result == DialogResult.OK)
{
    //Вывод пути к  
    //выбранной директории 
     textBox1.Text = fbd.SelectedPath;
}
      Вернитесь в конструктор главной формы и выполните двойной клик левой клавишей мыши по элементу управления «MonitoringInput»(CheckBox), вы перейдете в редактор кода с установкой курсора в автоматически созданном методе «MonitoringInput_CheckedChanged», события «CheckedChanged», возникающего при каждом изменении свойства «Check». Вставьте в тело данного метода приведенный ниже листинг формирования фильтра для элемента управления «fileSystemWatcher1».
//Получаем путь к выбранному каталогу.
string monitoredFolder = textBox1.Text;
//Определяем, указывает ли заданный путь 
//на существующий каталог на диске.
bool folderExists = Directory.Exists(monitoredFolder);

//Проверка существования директории.
if (folderExists)
{
    //Задаем путь отслеживаемого каталога.
    fileSystemWatcher1.Path = monitoredFolder;

    //Задаем строку фильтра, используемую для определения файлов,
    //контролируемых в каталоге. 
    //По умолчанию используется "*.*" (отслеживаются все файлы).       
    fileSystemWatcher1.Filter = textBox2.Text;

    //Задаем значение, показывающее необходимость контроля вложенных
    //каталогов по указанному пути.
    fileSystemWatcher1.IncludeSubdirectories = checkBox10.Checked;

    //Отслеживаемые изменения.
    NotifyFilters notificationFilters = new NotifyFilters();
    //Атрибуты файла и папки.
    if (checkBox2.Checked) notificationFilters = notificationFilters 
        | NotifyFilters.Attributes;
    //Время создания файла и папки.
    if (checkBox3.Checked) notificationFilters = notificationFilters
        | NotifyFilters.CreationTime;
    //Имя каталога.
    if (checkBox4.Checked) notificationFilters = notificationFilters
        | NotifyFilters.DirectoryName;
    //Имя файла
    if (checkBox5.Checked) notificationFilters = notificationFilters
        | NotifyFilters.FileName;
    //Дата последнего открытия файла или папки.
    if (checkBox6.Checked) notificationFilters = notificationFilters
        | NotifyFilters.LastAccess;
    //Дата последней записи в файл или папку.
    if (checkBox7.Checked) notificationFilters = notificationFilters
        | NotifyFilters.LastWrite;
    //Параметры безопасности файла или папки.
    if (checkBox8.Checked) notificationFilters = notificationFilters
        | NotifyFilters.Security;
    //Размер файла или папки.
    if (checkBox9.Checked) notificationFilters = notificationFilters
        | NotifyFilters.Size;
    //Задаем тип отслеживаемых изменений.
    fileSystemWatcher1.NotifyFilter = notificationFilters;

    //Задаем значение, определяющее, доступен ли данный компонент.
    fileSystemWatcher1.EnableRaisingEvents = checkBox1.Checked;
}
else if (checkBox1.Checked)
{
    MessageBox.Show(this, "Выбранная директория не существует!",
          "Мониторинг", MessageBoxButtons.OK, MessageBoxIcon.Error);
    //Выключаем мониторинг при ошибке.
    checkBox1.Checked = false;
}
//После запуске мониторинга, блокируем элементы управления.
textBox1.Enabled = textBox2.Enabled = 
    NotificationsGroup.Enabled = !checkBox1.Checked;
      Запустите ваш проект, нажав на клавиатуре клавишу «F5». У вас откроется главная форма проекта, нажмите кнопку «Открыть», для выбора каталога, в котором будут отслеживаться изменения. Для запуска отслеживания, установите галочку в элементе управления «checkBox1» (Задающем значение, определяющее, доступен ли элемент управления fileSystemWatcher1). После запуска у вас будут выводиться все события, которые вы настроили в фильтре.

Ссылка для скачивания примера: Яндекс.Диск


9 комментариев:

  1. При выполнении данного проекта срабатывает исключение. Как поступать в таком случае.

    ОтветитьУдалить
  2. Здравствуйте Лора, вышлите пожалуйста ваш проект через форму обратной связи, для проверки нашими специалистами.

    ОтветитьУдалить
  3. Спасибо. Проблема была в том, что документ был доступен только для чтения.

    ОтветитьУдалить
  4. Ошибка.При выключенном интернете пишет что я все равно в сети )

    ОтветитьУдалить
  5. Здравствуйте, а вы сетевой кабель вытаскивали или просто отключили интернет?

    ОтветитьУдалить
  6. Добрый вечер! Такая проблема, что делать?

    ОтветитьУдалить
  7. Здравствуйте, замените данную строку на:

    private List<TreeNode> CurrentNodeMatches = new List<TreeNode>();

    ОтветитьУдалить
  8. Здравствуйте дорогие друзья! Опыт в программировании совсем нулевой. Но очень интересно как это подключить к сайту ?

    ОтветитьУдалить
  9. А можно более детально, как решить проблему?
    У меня аналогичная ошибка.

    ОтветитьУдалить

Большая просьба, не писать в комментариях всякую ерунду не по теме!