Imports System.IO Imports DigitalData.Modules.Base.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 ''' ''' This may fire twice for a single save operation, ''' see: https://blogs.msdn.microsoft.com/oldnewthing/20140507-00/?p=1053/ ''' 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