[C#][VB] 指定ディレクトリ、ファイルの変更を監視する方法

[C#][VB] 指定ディレクトリ、ファイルの変更を監視する方法

C#, VB.NET で指定ディレクトリ、ファイルの変更を監視する方法

指定したパスのディレクトリやファイルを監視し、何かしらの変更があったタイミングで処理を実行するというようなことをC#, VB.NETで実現するには、System.IO.FileSystemWatcher クラスを使います。

イベントの種類

FileSystemWatcher では、指定したPathのファイルまたはディレクトリについて、次の状態変更が起こった時にイベントを発火できます。

  • Changed -> 変更されたときに発生
  • Created -> 作成されたときに発生
  • Deleted -> 削除されたときに発生
  • Renamed -> 名前が変更されたときに発生

監視対象

監視対象は、ディレクトリ単位での監視や指定ファイルのみの監視、ワイルドカードを使ったファイルの指定等さまざまな設定が可能です。

また、サブディレクトリ以下のファイルも同様に監視するかも設定できます。

サンプルコード

指定ディレクトリ以下のテキストファイルを監視するクラスのサンプルコードです。リネームのイベントは以下のいずれのパターンでも呼び出されます。

  • .txt -> .txt
  • .txt -> .xxx
  • .xxx -> .txt

C#

using System;
using System.IO;

static class TextFileWatcher
{
    private static FileSystemWatcher Watcher;

    public static void StartWatching()
    {
        var Watcher = new FileSystemWatcher();

        // 監視するパス
        Watcher.Path = @"c:\work";

        // ファイル名と最終書き込み時間
        Watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName;

        // フィルタで監視するファイルを.txtのみにする
        Watcher.Filter = "*.txt";

        // サブディレクトリ以下も監視する
        Watcher.IncludeSubdirectories = true;

        // 変更発生時のイベントを定義する
        Watcher.Created += Changed; // 新規作成
        Watcher.Changed += Changed; // 変更
        Watcher.Deleted += Changed; // 削除
        Watcher.Renamed += Changed; // リネーム

        // 監視開始
        Watcher.EnableRaisingEvents = true;

        // 必要がなくなったら監視終了処理(StopWatching)を呼ぶ
    }

    public static void Changed(object source, FileSystemEventArgs e)
    {
        switch (e.ChangeType)
        {
            case WatcherChangeTypes.Created:
                Console.WriteLine($"新規作成: {e.FullPath}");
                break;
            case WatcherChangeTypes.Deleted:
                Console.WriteLine($"削除: {e.FullPath}");
                break;
            case WatcherChangeTypes.Changed:
                Console.WriteLine($"変更: {e.FullPath}");
                break;
            case WatcherChangeTypes.Renamed:
                var renameEventArgs = e as RenamedEventArgs;
                Console.WriteLine($"リネーム: {renameEventArgs.OldFullPath} => {renameEventArgs.FullPath}");
                break;
        }
    }

    public static void StopWatching()
    {
        if (Watcher != null)
        {
            Watcher.EnableRaisingEvents = false;
            Watcher.Dispose();
        }
    }
}

VB.NET

Imports System.IO

Public Class TextFileWatcher
    Public Shared Watcher As FileSystemWatcher

    Public Shared Sub StartWatching()
        Watcher = New FileSystemWatcher()

        ' 監視するパス
        Watcher.Path = "c:\work"

        ' ファイル名と最終書き込み時間
        Watcher.NotifyFilter = NotifyFilters.LastWrite Or NotifyFilters.FileName

        ' フィルタで監視するファイルを.txtのみにする
        Watcher.Filter = "*.txt"

        ' サブディレクトリ以下も監視する
        Watcher.IncludeSubdirectories = True

        ' 変更発生時のイベントを定義する
        AddHandler Watcher.Created, AddressOf Changed ' 新規作成
        AddHandler Watcher.Changed, AddressOf Changed ' 変更
        AddHandler Watcher.Deleted, AddressOf Changed ' 削除
        AddHandler Watcher.Renamed, AddressOf Changed ' リネーム

        ' 監視開始
        Watcher.EnableRaisingEvents = True

        ' 必要がなくなったら監視終了処理(StopWatching)を呼ぶ
    End Sub

    Public Shared Sub Changed(ByVal source As Object, ByVal e As FileSystemEventArgs)
        Select Case e.ChangeType
            Case WatcherChangeTypes.Created
                Console.WriteLine($"新規作成: {e.FullPath}")
            Case WatcherChangeTypes.Changed
                Console.WriteLine($"変更: {e.FullPath}")
            Case WatcherChangeTypes.Deleted
                Console.WriteLine($"削除: {e.FullPath}")
            Case WatcherChangeTypes.Renamed
                Dim renameEventArgs = DirectCast(e, RenamedEventArgs)
                Console.WriteLine($"リネーム: {renameEventArgs.OldFullPath} => {renameEventArgs.FullPath}")
        End Select
    End Sub

    Public Shared Sub StopWatching()
        If (Not IsNothing(Watcher)) Then
            Watcher.EnableRaisingEvents = False
            Watcher.Dispose()
        End If
    End Sub
End Class

Changed が複数回呼ばれる

ファイルに書き込みを行った場合に発火する Changed イベントが、1回の書き込みのはずなのに複数回呼ばれることがあります。これはアプリケーションが複数回に分けて書き込みを行っているかららしく、FileSystemWatcher の問題ではありません。

複数回呼ばれるのが問題となるようであれば別途制御を入れなければなりません。

以上。

参考URL

C#カテゴリの最新記事