主婦と.NETと犬のぶろぐ

奥様 と プログラム と お犬様 の 楽しい日常

目次

Blog 利用状況

ニュース

書庫

日記カテゴリ

FileSystemWatcher(System.IO.FileSystemWatcher)

ホントに便利っすよねーこれ。
一回だけ使った事あった、かな...?

普通に使うと非同期でファイル監視をしてくれます。
WaitForChanged を使うと、同期でファイル監視を行います。(つまり、WaitForChanged がすぐに実行される。)
でも何故か同期の通信が私の環境ではうまくいかず、常にタイムアウトしてしまいました。
なんでだろ... noteWatcher.Path プロパティを WATCH_PATH にしてもうまくいかず、
ためしに FileSystemWatcher1.Path に REMOTE_PATH を設定してみたらうまくいったんすよ。
だから、ローカルとかリモートとかは関係ないんじゃないかなぁと。
なにが間違ってんのかな~。

■参考文献
ファイル システム イベントへの応答
FileSystemWatcher クラス
NotifyFilters 列挙体
FileSystemEventArgs クラス
ErrorEventArgs クラス
RenamedEventArgs クラス
WatcherChangeTypes 列挙体

■実行画像
実行したところ
FileSystemWatcher

Public Class FileSystemWatcherTest

Private Const WATCH_PATH As String = "D:\わんくま" Private Const REMOTE_PATH As String = "\\naoko_note\わんくま"
Private Sub FileSystemWatcherTest_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Me.ListBox1.Items.Clear() With Me.FileSystemWatcher1 .BeginInit() .Path = WATCH_PATH .Filter = "" ' すべてを監視する .IncludeSubdirectories = True ' サブディレクトリも監視 ' バッファサイズを指定する。適切なバッファサイズに関しては、以下参照 ' http://msdn2.microsoft.com/ja-jp/library/ded0dc5s(VS.80).aspx .InternalBufferSize = 4092 ' NotifyFilter に設定する値によって、通知の種類を選択する。 ' 今回は全部設定してみた。 .NotifyFilter = System.IO.NotifyFilters.Attributes Or _ System.IO.NotifyFilters.CreationTime Or _ System.IO.NotifyFilters.DirectoryName Or _ System.IO.NotifyFilters.FileName Or _ System.IO.NotifyFilters.LastAccess Or _ System.IO.NotifyFilters.LastWrite Or _ System.IO.NotifyFilters.Security Or _ System.IO.NotifyFilters.Size .EnableRaisingEvents = True ' 監視する .EndInit() End With End Sub
' ディレクトリ(IncludeSubdirectories=True の時のみ)またはファイルが作成された Private Sub FileSystemWatcher1_Created(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Created Me.Notify("FileSystemWatcher1.Created", e) End Sub
' ディレクトリ(IncludeSubdirectories=True の時のみ)またはファイルのサイズ、 ' システム属性、最終書き込み時刻、最終アクセス時刻、または NTFS セキュリティ アクセス許可が変更 Private Sub FileSystemWatcher1_Changed(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Changed Me.Notify("FileSystemWatcher1.Changed", e) End Sub
' ディレクトリ(IncludeSubdirectories=True の時のみ)またはファイルの名前が変更された Private Sub FileSystemWatcher1_Renamed(ByVal sender As Object, ByVal e As System.IO.RenamedEventArgs) Handles FileSystemWatcher1.Renamed With Me.ListBox1.Items .Add(StrDup(20, "=")) .Add("◆FileSystemWatcher1.Renamed◆") .Add("ChangeType:" & e.ChangeType.ToString()) .Add("OldFullPath:" & e.OldFullPath) .Add("OldName:" & e.OldName) .Add("FullPath:" & e.FullPath) .Add("Name:" & e.Name) End With
' 更に詳細な情報を得る Dim info As System.IO.FileSystemInfo = New System.IO.FileInfo(e.FullPath) System.Diagnostics.Debug.WriteLine("Attributes:" & info.Attributes.ToString()) If info.Attributes = IO.FileAttributes.Directory Then System.Diagnostics.Debug.WriteLine("DirectoryName:" & System.IO.Path.GetFileName(e.FullPath)) Else System.Diagnostics.Debug.WriteLine("LastName:" & System.IO.Path.GetFileName(e.FullPath)) End If System.Diagnostics.Debug.WriteLine("CreationTimeUtc:" & info.CreationTimeUtc.ToString()) System.Diagnostics.Debug.WriteLine("LastAccessTimeUtc:" & info.LastAccessTimeUtc.ToString()) End Sub
' バッファオーバーフロー時に発生する Private Sub FileSystemWatcher1_Error(ByVal sender As Object, ByVal e As System.IO.ErrorEventArgs) Handles FileSystemWatcher1.Error With Me.ListBox1.Items .Add(StrDup(20, "=")) .Add("◆FileSystemWatcher1.Error◆") .Add("Exception Name:" & e.GetException().GetType.Name) .Add("Exception Message:" & e.GetException().Message) End With End Sub
' ディレクトリ(IncludeSubdirectories=True の時のみ)または削除が作成された Private Sub FileSystemWatcher1_Deleted(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) Handles FileSystemWatcher1.Deleted Me.Notify("FileSystemWatcher1.Deleted", e) End Sub
Private Sub Notify(ByVal eventName As String, ByVal e As System.IO.FileSystemEventArgs) With Me.ListBox1.Items .Add(StrDup(20, "=")) .Add("◆" & eventName & "◆") .Add("ChangeType:" & e.ChangeType.ToString()) .Add("FullPath:" & e.FullPath) .Add("Name:" & e.Name) End With End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' 違う PC の監視を同期で行う Dim noteWatcher As System.IO.FileSystemWatcher = New System.IO.FileSystemWatcher With noteWatcher .BeginInit() .Path = REMOTE_PATH .Filter = "*.txt" ' テキストファイルだけ監視する。"wankuma.txt" のようにファイル名を直接指定してもOK .IncludeSubdirectories = False ' サブディレクトリは含まない ' 最終アクセス日時、最終更新日時、ファイル名の変更 を通知 .NotifyFilter = System.IO.NotifyFilters.LastAccess Or _ System.IO.NotifyFilters.LastWrite Or _ System.IO.NotifyFilters.FileName .SynchronizingObject = Me .EnableRaisingEvents = True ' 監視する .EndInit() End With
' 以下、同期通信による監視 Dim result As System.IO.WaitForChangedResult = _ noteWatcher.WaitForChanged(IO.WatcherChangeTypes.All)
With Me.ListBox1.Items .Add(StrDup(20, "=")) .Add("◇WaitForChanged◇") .Add("TimedOut:" & result.TimedOut) .Add("ChangeType:" & result.ChangeType.ToString()) .Add("OldName:" & result.OldName) .Add("Name:" & result.Name) End With noteWatcher.EnableRaisingEvents = False noteWatcher.Dispose() End Sub
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click ' 監視をやめる Me.FileSystemWatcher1.EnableRaisingEvents = False End Sub End Class

投稿日時 : 2007年1月17日 9:27

Feedback

# re: FileSystemWatcher(System.IO.FileSystemWatcher) 2007/01/17 10:43 じゃんぬねっと

FileSystemWatcher は、完全無欠でないので、自前のロジックと組み合わせることが必須ですね。

# re: FileSystemWatcher(System.IO.FileSystemWatcher) 2007/01/17 14:28 渋木宏明(ひどり)

そう、1つのファイル操作も漏らさずイベント通知してくれるわけではないのです。
同時期に多量のファイル操作が発生した場合、通知がはしょられる時があります。
その前提に立ってコードを書かないと、痛い目を見ます。

# re: FileSystemWatcher(System.IO.FileSystemWatcher) 2007/01/17 16:02 なおこ(・∀・)

>> じゃんぬさん
>> ひどりさん
> はしょられる時があります。
なるほどー。そういうことがあるんすか。
知らなかったです。
勉強になりました。ありがとうございます。

タイトル  
名前  
Url
コメント