这是一个继承自FileSystemWatcher的类。
它负责配置、启用和禁用事件的引发,并具有基本的日志记录和报告功能。
FileSystemWatcher的配置:
.BeginInit() - .EndInit()
BeginInit() 用于防止在 FileSystemWatcher 设置完成之前引发事件。
.SynchronizingObject
将SynchronizingObject 设置为表单组件。由于FileSystemWatcher 事件是从系统线程池编组的,因此可以确保在创建组件的同一线程上调用事件委托。
如果 SynchronizingObject 为 null,则访问组件可能会导致异常,或者更糟的是,导致静默失败。
.InternalBufferSize
内部缓冲区用于存储事件寄存器和文件路径。大于默认值(8192 字节)的缓冲区可以防止缓冲区溢出,这会危及事件的上升。这里设置为 32768 字节。
.Path
对于网络驱动器/共享,请使用 UNC 路径。
如何使用它:
定义一个引用FileWatcher Class的公共对象:
Public FileWatch As FileWatcher
然后你可以在需要的时候初始化它:
FileWatch = New FileWatcher("[Path to watch]",
"*", 'All files
"[Path to LogFile]",
Me, 'Synchronizing Object
Me.[TextBox control used as monitor])
[TextBox control used as monitor] 可以是 Nothing 如果没有使用。
FileWatcher 不会立即开始引发/记录事件; EnableRaisingEvents属性在初始化方法中设置为False。
您可以使用它的方法启动和停止它的活动:
Me.FileWatch.StartWatcher()
Me.FileWatch.StopWatcher()
启动和停止FileWatcher 是一个已注册(记录)的活动。
List(Of DateTime) 用于存储这些事件。请参阅FW_EventLogger Class。
其他存储信息有:
- 已删除的文件数。
- 创建的文件数
- 注册事件的总数(用于比较)。
- 日志文件的大小。
ActivityReport() 属性返回一个简单的报告:
Dictionary(Of String, String) = FileWatcher.ActivityReport()
这是日志文件的样子:
00000001 - 2018/02/28 21:00:25 - File D:\Temp\New Text Document.txt has been created
00000002 - 2018/02/28 21:00:29 - File D:\Temp\New Microsoft Access Database.accdb has been created
00000003 - 2018/02/28 21:00:34 - File D:\Temp\New WinZip File.zip has been created
00000004 - 2018/02/28 21:00:44 - File D:\Temp\New Microsoft Access Database.accdb has been deleted
00000005 - 2018/02/28 21:00:44 - File D:\Temp\New Text Document.txt has been deleted
00000006 - 2018/02/28 21:00:44 - File D:\Temp\New WinZip File.zip has been deleted
限制: 如果请求(将 TextBox 控件引用传递给类初始化),则 UI 会通过
同步对象。如果 UI 线程由于某种原因很忙,则
底层 FileSystemWatcher 正在缓冲的事件将堆积起来。这
可以(并且因为它可以)导致事件丢失。这是
内部缓冲区设置为默认值的 4 倍的原因。无论如何,它
如果监视的活动很高,那将永远不够。在正常
条件下,它可以处理 10/秒。事件没有问题。除此之外,
使用 FIFO 队列缓冲区的异步代理方法必须
放置在事件侦听器和数据消费者之间。
基于:
Visual Studio 2013, Update 5
.Net Framework 4.7.1
更新为:
Visual Studio 2017, 15.8.4
.Net Framework 4.7.1
Imports System.Collections.Generic
Imports System.IO
Imports System.Windows.Forms
Public Class FileWatcher
Inherits FileSystemWatcher
Private EventLogger As FW_EventLogger
Private Prompt As TextBox = Nothing
Public Sub New()
Me.New("", "", "", Nothing, Nothing)
End Sub
Public Sub New(fswPath As String, fswFilter As String, logFile As String, SyncObject As Form, SyncPrompt As TextBox)
Me.Prompt = SyncPrompt
Me.EventLogger = New FW_EventLogger With {.LogFileName = logFile}
SetupFileWatcher(fswPath, fswFilter, SyncObject)
End Sub
Public Sub StartWatcher()
Me.EventLogger.TimeStart.Add(DateTime.UtcNow)
If Me.Prompt IsNot Nothing Then
Me.Prompt.AppendText(String.Format("Logger Start Time: {0}" +
Environment.NewLine, DateTime.UtcNow.ToString()))
End If
Me.EnableRaisingEvents = True
End Sub
Public Sub StopWatcher()
Me.EnableRaisingEvents = False
Me.EventLogger.TimeStop.Add(DateTime.UtcNow)
If Me.Prompt IsNot Nothing Then
Me.Prompt.AppendText(String.Format("Logger Stop Time: {0}" +
Environment.NewLine, DateTime.UtcNow.ToString()))
End If
End Sub
Public ReadOnly Property ActivityReport() As Dictionary(Of String, String)
Get
Return Me.CreateActivityReport()
End Get
End Property
Public Property PromptControl As TextBox
Get
Return Me.Prompt
End Get
Set(value As TextBox)
Me.Prompt = value
End Set
End Property
Public Sub SetupFileWatcher(fwPath As String, fwFilter As String, SyncObject As Form)
If fwPath.Length = 0 Then
Return
End If
Me.BeginInit()
Me.SynchronizingObject = SyncObject
Me.InternalBufferSize = 32768
Me.IncludeSubdirectories = True
Me.Filter = fwFilter
Me.Path = fwPath
Me.NotifyFilter = NotifyFilters.FileName Or NotifyFilters.CreationTime
Me.EnableRaisingEvents = False
'Set the handler to the events you want to receive
AddHandler Me.Created, New FileSystemEventHandler(AddressOf Me.OnCreated)
AddHandler Me.Deleted, New FileSystemEventHandler(AddressOf Me.OnDeleted)
'The other events, should they become necessary.
'this.Changed += new FileSystemEventHandler(this.OnChanged);
'this.Renamed += new RenamedEventHandler(this.OnRenamed);
Me.EndInit()
End Sub
Private Function CreateActivityReport() As Dictionary(Of String, String)
With Me.EventLogger
Dim log As New Dictionary(Of String, String)
log.Add("Created", .FileCreated.ToString())
log.Add("Deleted", .FileDeleted.ToString())
log.Add("TotalEvents", .EventsLogged.ToString())
log.Add("LogFileSize", If(File.Exists(.LogFileName), New FileInfo(.LogFileName).Length.ToString(), "N/A"))
log.Add("StartTime", If(.TimeStart.Count > 0, .TimeStart.First().ToString(), "Not Started"))
log.Add("LastStopTime", If(.TimeStop.Count > 0, .TimeStop.Last().ToString(), "Never"))
log.Add("Status", If(Me.EnableRaisingEvents = True, "Running", "Stopped"))
Return log
End With
End Function
Protected Overloads Sub OnCreated(sender As Object, e As FileSystemEventArgs)
Dim Msg As String = "File " & e.FullPath & " has been created"
Me.EventLogger.Update(Msg, FW_EventLogger.EventType.FileCreated)
If Me.Prompt IsNot Nothing Then
Me.Prompt.AppendText(Msg + Environment.NewLine)
Me.Prompt.ScrollToCaret()
End If
End Sub
Protected Overloads Sub OnDeleted(sender As Object, e As FileSystemEventArgs)
Dim Msg As String = "File " & e.FullPath & " has been deleted"
Me.EventLogger.Update(Msg, FW_EventLogger.EventType.FileDeleted)
If Me.Prompt IsNot Nothing Then
Me.Prompt.AppendText(Msg + Environment.NewLine)
Me.Prompt.ScrollToCaret()
End If
End Sub
'The Event Logger Class
Private Class FW_EventLogger
Sub New()
Me.TimeStart = New List(Of DateTime)
Me.TimeStop = New List(Of DateTime)
End Sub
Public Enum EventType As Integer
FileCreated = 0
FileDeleted
End Enum
Public Property FileDeleted As Integer
Public Property FileCreated As Integer
Public Property EventsLogged As Integer
Public Property TimeStart As List(Of DateTime)
Public Property TimeStop As List(Of DateTime)
Public Property LogFileName As String
Public Sub Update(NewEvent As String, TypeOfEvent As EventType)
If Me.LogFileName <> String.Empty Then
If TypeOfEvent = EventType.FileCreated Then Me.FileCreated += 1
If TypeOfEvent = EventType.FileDeleted Then Me.FileDeleted += 1
Me.EventsLogged += 1
Using LogFileWriter As StreamWriter = New StreamWriter(Me.LogFileName, True, Encoding.UTF8)
LogFileWriter.WriteLine(Me.EventsLogged.ToString().PadLeft(8, "0"c) +
" - {0} - {1}", DateTime.UtcNow.ToString("yyyy/MM/dd hh:mm:ss"), NewEvent)
End Using
End If
End Sub
End Class
End Class