目次
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
の問題ではありません。
複数回呼ばれるのが問題となるようであれば別途制御を入れなければなりません。
以上。
コメントを書く