Modules/Filesystem/FileWatcher.vb
2019-02-06 15:31:22 +01:00

133 lines
4.6 KiB
VB.net

Imports System.IO
Imports DigitalData.Modules.Filesystem
Imports DigitalData.Modules.Filesystem.FileWatcherFilters
Imports DigitalData.Modules.Logging
Public Class FileWatcher
' Internals
Private ReadOnly _Logger As Logger
Private ReadOnly _Watchers As List(Of FileSystemWatcher)
Private ReadOnly _Files As Dictionary(Of String, FileWatcherProperties)
Private ReadOnly _Filters As List(Of BaseFileFilter)
' Options
Private _Path As String
' Public Events
Public Event FileSaved(ByVal FullName As String, ByVal IsSpecial As Boolean)
Public Sub New(LogConfig As LogConfig, Path As String, Optional Filters As List(Of BaseFileFilter) = Nothing)
_Logger = LogConfig.GetLogger()
_Files = New Dictionary(Of String, FileWatcherProperties)
_Watchers = New List(Of FileSystemWatcher)
_Filters = IIf(IsNothing(Filters), GetDefaultFilters(), Filters)
_Path = Path
For Each oFilePath In Directory.EnumerateFiles(_Path)
Try
If IO.File.Exists(oFilePath) Then
_Files.Add(oFilePath, New FileWatcherProperties With {
.CreatedAt = DateTime.Now,
.ChangedAt = Nothing
})
End If
Catch ex As Exception
_Logger.Error(ex)
_Logger.Warn("File {0} cannot be watched!")
End Try
Next
End Sub
Public Sub Add(Filter As String)
_Watchers.Add(CreateWatcher(Filter))
End Sub
Public Sub Start()
For Each oWatcher In _Watchers
oWatcher.EnableRaisingEvents = True
Next
End Sub
Public Sub [Stop]()
For Each oWatcher In _Watchers
If Not IsNothing(oWatcher) Then
oWatcher.EnableRaisingEvents = False
oWatcher.Dispose()
End If
Next
End Sub
Private Function GetDefaultFilters()
Return New List(Of BaseFileFilter) From {
New TempFileFilter,
New OfficeFileFilter
}
End Function
Private Function CreateWatcher(Filter As String)
Dim oWatcher = New FileSystemWatcher() With {
.Path = _Path,
.Filter = Filter,
.NotifyFilter = NotifyFilters.LastAccess _
Or NotifyFilters.LastWrite _
Or NotifyFilters.FileName _
Or NotifyFilters.Size _
Or NotifyFilters.FileName _
Or NotifyFilters.Attributes
}
AddHandler oWatcher.Created, AddressOf HandleFileCreated
AddHandler oWatcher.Changed, AddressOf HandleFileChanged
AddHandler oWatcher.Deleted, AddressOf HandleFileDeleted
AddHandler oWatcher.Renamed, AddressOf HandleFileRenamed
Return oWatcher
End Function
Private Sub HandleFileCreated(sender As Object, e As FileSystemEventArgs)
_Files.Add(e.FullPath, New FileWatcherProperties())
_Logger.Debug("[Created] " & e.FullPath)
End Sub
''' <summary>
''' This may fire twice for a single save operation,
''' see: https://blogs.msdn.microsoft.com/oldnewthing/20140507-00/?p=1053/
''' </summary>
Private Sub HandleFileChanged(sender As Object, e As FileSystemEventArgs)
_Files.Item(e.FullPath).ChangedAt = DateTime.Now
_Logger.Debug("[Changed] " & e.FullPath)
Dim oShouldRaiseSave As Boolean = Not _Filters.Any(Function(oFilter)
Return oFilter.ShouldFilter(e)
End Function)
If oShouldRaiseSave Then
RaiseEvent FileSaved(e.FullPath, False)
End If
End Sub
Private Sub HandleFileDeleted(sender As Object, e As FileSystemEventArgs)
_Files.Remove(e.FullPath)
_Logger.Debug("[Removed] " & e.FullPath)
End Sub
Private Sub HandleFileRenamed(sender As Object, e As RenamedEventArgs)
Dim oProperties = _Files.Item(e.OldFullPath)
_Files.Remove(e.OldFullPath)
_Files.Add(e.FullPath, oProperties)
' Soll eine umbenannte datei als NEU gelten?
Dim oShouldRaiseSave = _Filters.Any(Function(oFilter)
Return oFilter.ShouldRaiseSave(e)
End Function)
If oShouldRaiseSave Then
RaiseEvent FileSaved(e.OldFullPath, True)
End If
_Logger.Debug("[Renamed] {0} --> {1}", e.OldFullPath, e.FullPath)
End Sub
End Class