フォルダやファイルが変更されたらすぐにそのことを知るための方法を紹介します。これは、System.IO.FileSystemWatcherクラスを使用すれば簡単にできます。ただしFileSystemWatcherクラスはWindows NT系のOSでしか使えませんので、Windows98/Meでは残念ながらできません。
フォルダまたはファイルが作成されたときにはCreatedイベントが、削除された時にはDeletedイベントが、名前が変更された時にはRenamedイベントが、サイズ、システム属性、最終書き込み時刻、最終アクセス時刻、またはセキュリティアクセス許可が変更されたときにはChangedイベントが発生します。
次の例では、フォルダ"C:\My Documents"内のTXTファイルの作成、削除、名前の変更を監視しています。WaitForChangedメソッドを使い同期的に監視しているため、監視中はフリーズしたようになります。
Dim watcher As New System.IO.FileSystemWatcher '監視するディレクトリを指定 watcher.Path = "C:\My Documents" '*.txtファイルを監視、すべて監視するときは""にする watcher.Filter = "*.txt" 'ファイル名とディレクトリ名と最終書き込む日時の変更を監視 watcher.NotifyFilter = System.IO.NotifyFilters.FileName Or _ System.IO.NotifyFilters.DirectoryName Or _ System.IO.NotifyFilters.LastWrite 'サブディレクトリは監視しない watcher.IncludeSubdirectories = False '必要に応じてバッファサイズを変更 'watcher.InternalBufferSize = 4096 '同期的に監視を開始する Dim changedResult As System.IO.WaitForChangedResult = _ watcher.WaitForChanged(System.IO.WatcherChangeTypes.All) If changedResult.TimedOut Then Console.WriteLine("タイムアウトしました。") Return End If '変更があったときに結果を表示する Select Case changedResult.ChangeType Case System.IO.WatcherChangeTypes.Changed Console.WriteLine(("ファイル 「" + _ changedResult.Name + "」が変更されました。")) Case System.IO.WatcherChangeTypes.Created Console.WriteLine(("ファイル 「" + _ changedResult.Name + "」が作成されました。")) Case System.IO.WatcherChangeTypes.Deleted Console.WriteLine(("ファイル 「" + _ changedResult.Name + "」が削除されました。")) Case System.IO.WatcherChangeTypes.Renamed Console.WriteLine(("ファイル 「" + _ changedResult.OldName + "」の名前が「" + _ changedResult.Name + "」に変更されました。")) End Select
System.IO.FileSystemWatcher watcher = new System.IO.FileSystemWatcher(); //監視するディレクトリを指定 watcher.Path = @"C:\My Documents"; //*.txtファイルを監視、すべて監視するときは""にする watcher.Filter = "*.txt"; //ファイル名とディレクトリ名と最終書き込む日時の変更を監視 watcher.NotifyFilter = System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.DirectoryName | System.IO.NotifyFilters.LastWrite; //サブディレクトリは監視しない watcher.IncludeSubdirectories = false; //必要に応じてバッファサイズを変更 //watcher.InternalBufferSize = 4096 //同期的に監視を開始する System.IO.WaitForChangedResult changedResult = watcher.WaitForChanged(System.IO.WatcherChangeTypes.All); if (changedResult.TimedOut) { Console.WriteLine("タイムアウトしました。"); return; } //変更があったときに結果を表示する switch (changedResult.ChangeType) { case System.IO.WatcherChangeTypes.Changed: Console.WriteLine( "ファイル 「" + changedResult.Name + "」が変更されました。"); break; case System.IO.WatcherChangeTypes.Created: Console.WriteLine( "ファイル 「" + changedResult.Name + "」が作成されました。"); break; case System.IO.WatcherChangeTypes.Deleted: Console.WriteLine( "ファイル 「" + changedResult.Name + "」が削除されました。"); break; case System.IO.WatcherChangeTypes.Renamed: Console.WriteLine( "ファイル 「" + changedResult.OldName + "」の名前が「" + changedResult.Name + "」に変更されました。"); break; }
次に非同期的に監視する例を紹介します。Button1をクリックすることにより監視を開始し、Button2をクリックすることにより監視を終了します。
Private watcher As System.IO.FileSystemWatcher = Nothing 'Button1のClickイベントハンドラ Private Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button1.Click If Not (watcher Is Nothing) Then Return End If watcher = New System.IO.FileSystemWatcher '監視するディレクトリを指定 watcher.Path = "C:\My Documents" '最終アクセス日時、最終更新日時、ファイル、フォルダ名の変更を監視する watcher.NotifyFilter = System.IO.NotifyFilters.LastAccess Or _ System.IO.NotifyFilters.LastWrite Or _ System.IO.NotifyFilters.FileName Or _ System.IO.NotifyFilters.DirectoryName 'すべてのファイルを監視 watcher.Filter = "" 'UIのスレッドにマーシャリングする 'コンソールアプリケーションでの使用では必要ない watcher.SynchronizingObject = Me 'イベントハンドラの追加 AddHandler watcher.Changed, AddressOf watcher_Changed AddHandler watcher.Created, AddressOf watcher_Changed AddHandler watcher.Deleted, AddressOf watcher_Changed AddHandler watcher.Renamed, AddressOf watcher_Renamed '監視を開始する watcher.EnableRaisingEvents = True Console.WriteLine("監視を開始しました。") End Sub 'Button2のClickイベントハンドラ Private Sub Button2_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Handles Button2.Click '監視を終了 watcher.EnableRaisingEvents = False watcher.Dispose() watcher = Nothing Console.WriteLine("監視を終了しました。") End Sub 'イベントハンドラ Private Sub watcher_Changed(ByVal source As System.Object, _ ByVal e As System.IO.FileSystemEventArgs) Select Case e.ChangeType Case System.IO.WatcherChangeTypes.Changed Console.WriteLine(("ファイル 「" + e.FullPath + _ "」が変更されました。")) Case System.IO.WatcherChangeTypes.Created Console.WriteLine(("ファイル 「" + e.FullPath + _ "」が作成されました。")) Case System.IO.WatcherChangeTypes.Deleted Console.WriteLine(("ファイル 「" + e.FullPath + _ "」が削除されました。")) End Select End Sub Private Sub watcher_Renamed(ByVal source As System.Object, _ ByVal e As System.IO.RenamedEventArgs) Console.WriteLine(("ファイル 「" + e.FullPath + _ "」の名前が変更されました。")) End Sub
private System.IO.FileSystemWatcher watcher = null; //Button1のClickイベントハンドラ private void Button1_Click(object sender, System.EventArgs e) { if (watcher != null) return; watcher = new System.IO.FileSystemWatcher(); //監視するディレクトリを指定 watcher.Path = @"C:\My Documents"; //最終アクセス日時、最終更新日時、ファイル、フォルダ名の変更を監視する watcher.NotifyFilter = (System.IO.NotifyFilters.LastAccess | System.IO.NotifyFilters.LastWrite | System.IO.NotifyFilters.FileName | System.IO.NotifyFilters.DirectoryName); //すべてのファイルを監視 watcher.Filter = ""; //UIのスレッドにマーシャリングする //コンソールアプリケーションでの使用では必要ない watcher.SynchronizingObject = this; //イベントハンドラの追加 watcher.Changed += new System.IO.FileSystemEventHandler(watcher_Changed); watcher.Created += new System.IO.FileSystemEventHandler(watcher_Changed); watcher.Deleted += new System.IO.FileSystemEventHandler(watcher_Changed); watcher.Renamed += new System.IO.RenamedEventHandler(watcher_Renamed); //監視を開始する watcher.EnableRaisingEvents = true; Console.WriteLine("監視を開始しました。"); } //Button2のClickイベントハンドラ private void Button2_Click(object sender, System.EventArgs e) { //監視を終了 watcher.EnableRaisingEvents = false; watcher.Dispose(); watcher = null; Console.WriteLine("監視を終了しました。"); } //イベントハンドラ private void watcher_Changed(System.Object source, System.IO.FileSystemEventArgs e) { switch (e.ChangeType) { case System.IO.WatcherChangeTypes.Changed: Console.WriteLine( "ファイル 「" + e.FullPath + "」が変更されました。"); break; case System.IO.WatcherChangeTypes.Created: Console.WriteLine( "ファイル 「" + e.FullPath + "」が作成されました。"); break; case System.IO.WatcherChangeTypes.Deleted: Console.WriteLine( "ファイル 「" + e.FullPath + "」が削除されました。"); break; } } private void watcher_Renamed(System.Object source, System.IO.RenamedEventArgs e) { Console.WriteLine( "ファイル 「" + e.FullPath + "」の名前が変更されました。"); }
上の例では、コードだけですべて行いましたが、Visual Studioのフォームデザイナを使用すれば、「ツールボックス」の「コンポーネント」タブにある「FileSystemWatcher」をフォームに配置するだけで簡単に使用できます。
注意:非同期で監視を行う場合、SynchronizingObjectの意味等のマルチスレッドプログラミングの知識がないと危険です。これについて詳しくは、こちらをご覧ください。