将条目号附加到 FileSystemWatcher 输出
appending an entry number to FileSystemWatcher output
好的,
可能会被视为一个非常成熟的 post 在这里,我不是很擅长 VB 或很多程序员,但我在 "learn by doing" 驱动器上.
我正在开发一个应用程序,它为用户创建目录,并使用 FileSystemWatcher 跟踪创建的目录和对这些目录的更改。
到目前为止我已经得到了这个小片段(在回答你的评论时更新了 Jimi):
Button_Click 的私人订阅者:
watchfolder = New System.IO.FileSystemWatcher()
watchfolder.Path = TodaysScanFolder
watchfolder.Filter = ""
watchfolder.IncludeSubdirectories = True
watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or
IO.NotifyFilters.FileName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or
IO.NotifyFilters.Attributes
AddHandler watchfolder.Created, AddressOf logchange
AddHandler watchfolder.Deleted, AddressOf logchange
watchfolder.EnableRaisingEvents = True
btnStartScan.Enabled = False
btnStopScan.Enabled = True
End Sub
Public Sub logchange(ByVal source As Object, ByVal e As _
System.IO.FileSystemEventArgs)
If e.ChangeType = IO.WatcherChangeTypes.Created Then
txt_folderactivity.Text &= "File " & e.FullPath &
" has been created" & vbCrLf
End If
If e.ChangeType = IO.WatcherChangeTypes.Deleted Then
txt_folderactivity.Text &= "File " & e.FullPath &
" has been deleted" & vbCrLf
End If
End Sub
对于每个额外的 activity,我想在此之前将输出附加到 txt_folderactivity.Text 和 1。然后是 2、3,依此类推。
您会看到这个文本框,在更改时将输出写入文本文件,如下所示:
Private Sub txt_folderactivity_TextChanged(sender As Object, e As EventArgs) Handles txt_folderactivity.TextChanged
str = txt_folderactivity.Text
My.Computer.FileSystem.WriteAllText(LogFileLoc, str, True)
End Sub
我希望该文本文件的每个 line/entry 都以 1、2、3 等开头。另外,正如我所说 VB 的初学者,似乎拼凑了一些看起来有点乱但实用且对业务至关重要的东西,任何有关相关 VB 学习资源的良好开端的指示都会很有帮助。谢谢大家
这是继承自 FileSystemWatcher
的 class。
它负责配置、启用和禁用事件的引发并具有基本的日志记录和报告功能。
FileSystemWatcher
的配置:
.BeginInit()
- .EndInit()
BeginInit()
用于防止在 FileSystemWatcher
设置完成之前引发事件。
.SynchronizingObject
将 SynchronizingObject
设置为表单组件。由于 FileSystemWatcher
事件是从系统线程池中编组的,这确保了在创建组件的同一线程上调用事件委托。
如果 SynchronizingObject
为 null,则访问该组件可能会导致异常,或者更糟的是,会导致静默失败。
.InternalBufferSize
内部缓冲区用于存储事件寄存器和文件路径。大于默认值(8192 字节)的缓冲区可以防止缓冲区溢出,从而影响事件的发生。这里设置为32768字节。
.Path
对于网络 drives/shares 使用 UNC 路径。
使用方法:
定义一个引用 FileWatcher Class
:
的 public 对象
Public FileWatch As FileWatcher
然后你可以随时初始化它:
FileWatch = New FileWatcher("[Path to watch]",
"*", 'All files
"[Path to LogFile]",
Me, 'Synchronizing Object
[TextBox control used as monitor])
[TextBox control used as monitor]
如果使用none可以是Nothing
。
FileWatcher
不会立即开始 raise/log 事件; EnableRaisingEvents
属性 在初始化方法中设置为 False
。
您可以使用其方法启动和停止其 activity:
FileWatch.StartWatcher()
FileWatch.StopWatcher()
启动和停止 FileWatcher
是已注册(记录)的 activity。
一个 List(Of DateTime)
用于存储这些事件。见 FW_EventLogger Class
.
其他存储的信息是:
- 删除的文件数
- 创建的文件数
- 注册事件总数(用于比较)
- 日志文件的大小
ActivityReport()
属性returns一个简单的报告:
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 控件引用传递给 class 初始化),UI 通过同步对象同步更新。如果 UI 线程由于某种原因忙,底层 FileSystemWatcher 正在缓冲的事件将会堆积起来。这会(并且因为它会)导致事件丢失。这就是内部缓冲区设置为默认值 4 倍的原因。无论如何,如果监控 activity 很高,那将永远不够。在正常情况下,它可以处理 10 个/秒。事件没有问题。除此之外,必须在事件侦听器和数据使用者之间放置一个使用 FIFO 队列缓冲区的异步代理方法。
测试:
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)
Prompt = SyncPrompt
EventLogger = New FW_EventLogger With {.LogFileName = logFile}
SetupFileWatcher(fswPath, fswFilter, SyncObject)
End Sub
Public Sub StartWatcher()
EventLogger.TimeStart.Add(DateTime.UtcNow)
If Prompt IsNot Nothing Then
Prompt.AppendText(String.Format("Logger Start Time: {0}" +
Environment.NewLine, DateTime.UtcNow.ToString()))
End If
EnableRaisingEvents = True
End Sub
Public Sub StopWatcher()
EnableRaisingEvents = False
EventLogger.TimeStop.Add(DateTime.UtcNow)
If Prompt IsNot Nothing Then
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 CreateActivityReport()
End Get
End Property
Public Property PromptControl As TextBox
Get
Return Prompt
End Get
Set(value As TextBox)
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
BeginInit()
SynchronizingObject = SyncObject
InternalBufferSize = 32768
IncludeSubdirectories = True
Filter = fwFilter
Path = fwPath
NotifyFilter = NotifyFilters.FileName Or NotifyFilters.CreationTime
EnableRaisingEvents = False
'Set the handler to the events you want to receive
AddHandler Created, New FileSystemEventHandler(AddressOf OnCreated)
AddHandler Deleted, New FileSystemEventHandler(AddressOf OnDeleted)
'The other events, should they become necessary.
'AddHandler Changed, New FileSystemEventHandler(AddressOf OnChanged);
'AddHandler Renamed, New RenamedEventHandler(AddressOf OnRenamed);
EndInit()
End Sub
Private Function CreateActivityReport() As Dictionary(Of String, String)
With 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(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"
EventLogger.Update(Msg, FW_EventLogger.EventType.FileCreated)
If Prompt IsNot Nothing Then
Prompt.AppendText(Msg + Environment.NewLine)
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"
EventLogger.Update(Msg, FW_EventLogger.EventType.FileDeleted)
If Prompt IsNot Nothing Then
Prompt.AppendText(Msg + Environment.NewLine)
Prompt.ScrollToCaret()
End If
End Sub
'The Event Logger Class
Private Class FW_EventLogger
Sub New()
TimeStart = New List(Of DateTime)
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 Not String.IsNullOrEmpty(LogFileName) Then
If TypeOfEvent = EventType.FileCreated Then FileCreated += 1
If TypeOfEvent = EventType.FileDeleted Then FileDeleted += 1
EventsLogged += 1
Using LogFileWriter As StreamWriter = New StreamWriter(LogFileName, True, Encoding.UTF8)
LogFileWriter.WriteLine(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
好的,
可能会被视为一个非常成熟的 post 在这里,我不是很擅长 VB 或很多程序员,但我在 "learn by doing" 驱动器上.
我正在开发一个应用程序,它为用户创建目录,并使用 FileSystemWatcher 跟踪创建的目录和对这些目录的更改。
到目前为止我已经得到了这个小片段(在回答你的评论时更新了 Jimi):
Button_Click 的私人订阅者:
watchfolder = New System.IO.FileSystemWatcher()
watchfolder.Path = TodaysScanFolder
watchfolder.Filter = ""
watchfolder.IncludeSubdirectories = True
watchfolder.NotifyFilter = IO.NotifyFilters.DirectoryName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or
IO.NotifyFilters.FileName
watchfolder.NotifyFilter = watchfolder.NotifyFilter Or
IO.NotifyFilters.Attributes
AddHandler watchfolder.Created, AddressOf logchange
AddHandler watchfolder.Deleted, AddressOf logchange
watchfolder.EnableRaisingEvents = True
btnStartScan.Enabled = False
btnStopScan.Enabled = True
End Sub
Public Sub logchange(ByVal source As Object, ByVal e As _
System.IO.FileSystemEventArgs)
If e.ChangeType = IO.WatcherChangeTypes.Created Then
txt_folderactivity.Text &= "File " & e.FullPath &
" has been created" & vbCrLf
End If
If e.ChangeType = IO.WatcherChangeTypes.Deleted Then
txt_folderactivity.Text &= "File " & e.FullPath &
" has been deleted" & vbCrLf
End If
End Sub
对于每个额外的 activity,我想在此之前将输出附加到 txt_folderactivity.Text 和 1。然后是 2、3,依此类推。
您会看到这个文本框,在更改时将输出写入文本文件,如下所示:
Private Sub txt_folderactivity_TextChanged(sender As Object, e As EventArgs) Handles txt_folderactivity.TextChanged
str = txt_folderactivity.Text
My.Computer.FileSystem.WriteAllText(LogFileLoc, str, True)
End Sub
我希望该文本文件的每个 line/entry 都以 1、2、3 等开头。另外,正如我所说 VB 的初学者,似乎拼凑了一些看起来有点乱但实用且对业务至关重要的东西,任何有关相关 VB 学习资源的良好开端的指示都会很有帮助。谢谢大家
这是继承自 FileSystemWatcher
的 class。
它负责配置、启用和禁用事件的引发并具有基本的日志记录和报告功能。
FileSystemWatcher
的配置:
.BeginInit()
- .EndInit()
BeginInit()
用于防止在 FileSystemWatcher
设置完成之前引发事件。
.SynchronizingObject
将 SynchronizingObject
设置为表单组件。由于 FileSystemWatcher
事件是从系统线程池中编组的,这确保了在创建组件的同一线程上调用事件委托。
如果 SynchronizingObject
为 null,则访问该组件可能会导致异常,或者更糟的是,会导致静默失败。
.InternalBufferSize
内部缓冲区用于存储事件寄存器和文件路径。大于默认值(8192 字节)的缓冲区可以防止缓冲区溢出,从而影响事件的发生。这里设置为32768字节。
.Path
对于网络 drives/shares 使用 UNC 路径。
使用方法:
定义一个引用 FileWatcher Class
:
Public FileWatch As FileWatcher
然后你可以随时初始化它:
FileWatch = New FileWatcher("[Path to watch]",
"*", 'All files
"[Path to LogFile]",
Me, 'Synchronizing Object
[TextBox control used as monitor])
[TextBox control used as monitor]
如果使用none可以是Nothing
。
FileWatcher
不会立即开始 raise/log 事件; EnableRaisingEvents
属性 在初始化方法中设置为 False
。
您可以使用其方法启动和停止其 activity:
FileWatch.StartWatcher()
FileWatch.StopWatcher()
启动和停止 FileWatcher
是已注册(记录)的 activity。
一个 List(Of DateTime)
用于存储这些事件。见 FW_EventLogger Class
.
其他存储的信息是:
- 删除的文件数
- 创建的文件数
- 注册事件总数(用于比较)
- 日志文件的大小
ActivityReport()
属性returns一个简单的报告:
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 控件引用传递给 class 初始化),UI 通过同步对象同步更新。如果 UI 线程由于某种原因忙,底层 FileSystemWatcher 正在缓冲的事件将会堆积起来。这会(并且因为它会)导致事件丢失。这就是内部缓冲区设置为默认值 4 倍的原因。无论如何,如果监控 activity 很高,那将永远不够。在正常情况下,它可以处理 10 个/秒。事件没有问题。除此之外,必须在事件侦听器和数据使用者之间放置一个使用 FIFO 队列缓冲区的异步代理方法。
测试:
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)
Prompt = SyncPrompt
EventLogger = New FW_EventLogger With {.LogFileName = logFile}
SetupFileWatcher(fswPath, fswFilter, SyncObject)
End Sub
Public Sub StartWatcher()
EventLogger.TimeStart.Add(DateTime.UtcNow)
If Prompt IsNot Nothing Then
Prompt.AppendText(String.Format("Logger Start Time: {0}" +
Environment.NewLine, DateTime.UtcNow.ToString()))
End If
EnableRaisingEvents = True
End Sub
Public Sub StopWatcher()
EnableRaisingEvents = False
EventLogger.TimeStop.Add(DateTime.UtcNow)
If Prompt IsNot Nothing Then
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 CreateActivityReport()
End Get
End Property
Public Property PromptControl As TextBox
Get
Return Prompt
End Get
Set(value As TextBox)
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
BeginInit()
SynchronizingObject = SyncObject
InternalBufferSize = 32768
IncludeSubdirectories = True
Filter = fwFilter
Path = fwPath
NotifyFilter = NotifyFilters.FileName Or NotifyFilters.CreationTime
EnableRaisingEvents = False
'Set the handler to the events you want to receive
AddHandler Created, New FileSystemEventHandler(AddressOf OnCreated)
AddHandler Deleted, New FileSystemEventHandler(AddressOf OnDeleted)
'The other events, should they become necessary.
'AddHandler Changed, New FileSystemEventHandler(AddressOf OnChanged);
'AddHandler Renamed, New RenamedEventHandler(AddressOf OnRenamed);
EndInit()
End Sub
Private Function CreateActivityReport() As Dictionary(Of String, String)
With 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(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"
EventLogger.Update(Msg, FW_EventLogger.EventType.FileCreated)
If Prompt IsNot Nothing Then
Prompt.AppendText(Msg + Environment.NewLine)
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"
EventLogger.Update(Msg, FW_EventLogger.EventType.FileDeleted)
If Prompt IsNot Nothing Then
Prompt.AppendText(Msg + Environment.NewLine)
Prompt.ScrollToCaret()
End If
End Sub
'The Event Logger Class
Private Class FW_EventLogger
Sub New()
TimeStart = New List(Of DateTime)
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 Not String.IsNullOrEmpty(LogFileName) Then
If TypeOfEvent = EventType.FileCreated Then FileCreated += 1
If TypeOfEvent = EventType.FileDeleted Then FileDeleted += 1
EventsLogged += 1
Using LogFileWriter As StreamWriter = New StreamWriter(LogFileName, True, Encoding.UTF8)
LogFileWriter.WriteLine(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