jj: filewatcher
This commit is contained in:
parent
a1c96731ef
commit
fedc45a88b
@ -1,25 +1,33 @@
|
|||||||
Imports System.IO
|
Imports System.IO
|
||||||
|
Imports DigitalData.Modules.Filesystem
|
||||||
|
Imports DigitalData.Modules.Filesystem.FileWatcherFilters
|
||||||
Imports DigitalData.Modules.Logging
|
Imports DigitalData.Modules.Logging
|
||||||
|
|
||||||
|
|
||||||
Public Class FileWatcher
|
Public Class FileWatcher
|
||||||
|
' Internals
|
||||||
Private ReadOnly _Logger As Logger
|
Private ReadOnly _Logger As Logger
|
||||||
Private ReadOnly _Watchers As List(Of FileSystemWatcher)
|
Private ReadOnly _Watchers As List(Of FileSystemWatcher)
|
||||||
Private ReadOnly _Files As Dictionary(Of String, FileProperties)
|
Private ReadOnly _Files As Dictionary(Of String, FileWatcherProperties)
|
||||||
|
Private ReadOnly _Filters As List(Of BaseFileFilter)
|
||||||
|
|
||||||
|
' Options
|
||||||
Private _Path As String
|
Private _Path As String
|
||||||
|
|
||||||
Public OfficeFilters As New List(Of String) From {"docx", "xlsx", "pptx"}
|
' Public Events
|
||||||
|
Public Event FileSaved(ByVal FullName As String, ByVal IsSpecial As Boolean)
|
||||||
|
|
||||||
Public Sub New(LogConfig As LogConfig, Path As String)
|
Public Sub New(LogConfig As LogConfig, Path As String, Optional Filters As List(Of BaseFileFilter) = Nothing)
|
||||||
_Logger = LogConfig.GetLogger()
|
_Logger = LogConfig.GetLogger()
|
||||||
_Files = New Dictionary(Of String, FileProperties)
|
_Files = New Dictionary(Of String, FileWatcherProperties)
|
||||||
_Watchers = New List(Of FileSystemWatcher)
|
_Watchers = New List(Of FileSystemWatcher)
|
||||||
|
_Filters = IIf(IsNothing(Filters), GetDefaultFilters(), Filters)
|
||||||
_Path = Path
|
_Path = Path
|
||||||
|
|
||||||
For Each oFilePath As String In Directory.EnumerateFiles(_Path)
|
For Each oFilePath In Directory.EnumerateFiles(_Path)
|
||||||
Try
|
Try
|
||||||
If IO.File.Exists(oFilePath) Then
|
If IO.File.Exists(oFilePath) Then
|
||||||
_Files.Add(oFilePath, New FileProperties With {
|
_Files.Add(oFilePath, New FileWatcherProperties With {
|
||||||
.CreatedAt = DateTime.Now,
|
.CreatedAt = DateTime.Now,
|
||||||
.ChangedAt = Nothing
|
.ChangedAt = Nothing
|
||||||
})
|
})
|
||||||
@ -31,58 +39,10 @@ Public Class FileWatcher
|
|||||||
Next
|
Next
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Sub Add(Filter As String, Optional SpecialTreatmentFilters As List(Of String) = Nothing)
|
Public Sub Add(Filter As String)
|
||||||
_Watchers.Add(CreateWatcher(Filter))
|
_Watchers.Add(CreateWatcher(Filter))
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Sub Add(Filters As List(Of String), Optional SpecialTreatmentFilters As List(Of String) = Nothing)
|
|
||||||
For Each oFilter In Filters
|
|
||||||
_Watchers.Add(CreateWatcher(oFilter))
|
|
||||||
Next
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Private Function CreateWatcher(Filter As String)
|
|
||||||
Dim oWatcher = New FileSystemWatcher() With {
|
|
||||||
.Path = _Path,
|
|
||||||
.Filter = Filter,
|
|
||||||
.NotifyFilter = NotifyFilters.CreationTime _
|
|
||||||
Or NotifyFilters.LastAccess _
|
|
||||||
Or NotifyFilters.LastWrite _
|
|
||||||
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 FileProperties())
|
|
||||||
_Logger.Info("[Created] " & e.FullPath)
|
|
||||||
End Sub
|
|
||||||
Private Sub HandleFileChanged(sender As Object, e As FileSystemEventArgs)
|
|
||||||
_Files.Item(e.FullPath).ChangedAt = DateTime.Now
|
|
||||||
_Logger.Info("[Changed] " & e.FullPath)
|
|
||||||
End Sub
|
|
||||||
Private Sub HandleFileDeleted(sender As Object, e As FileSystemEventArgs)
|
|
||||||
_Files.Remove(e.FullPath)
|
|
||||||
_Logger.Info("[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?
|
|
||||||
|
|
||||||
_Logger.Info("[Renamed] {0} --> {1}", e.OldFullPath, e.FullPath)
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Public Sub Start()
|
Public Sub Start()
|
||||||
For Each oWatcher In _Watchers
|
For Each oWatcher In _Watchers
|
||||||
oWatcher.EnableRaisingEvents = True
|
oWatcher.EnableRaisingEvents = True
|
||||||
@ -98,13 +58,75 @@ Public Class FileWatcher
|
|||||||
Next
|
Next
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
Public Class FileProperties
|
Private Function GetDefaultFilters()
|
||||||
Public CreatedAt As DateTime
|
Return New List(Of BaseFileFilter) From {
|
||||||
Public ChangedAt As DateTime
|
New TempFileFilter,
|
||||||
|
New OfficeFileFilter
|
||||||
|
}
|
||||||
|
End Function
|
||||||
|
|
||||||
Public Sub New()
|
Private Function CreateWatcher(Filter As String)
|
||||||
CreatedAt = DateTime.Now
|
Dim oWatcher = New FileSystemWatcher() With {
|
||||||
ChangedAt = Nothing
|
.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
|
End Sub
|
||||||
End Class
|
|
||||||
|
''' <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
|
End Class
|
||||||
|
|||||||
61
Filesystem/FileWatcherFilters.vb
Normal file
61
Filesystem/FileWatcherFilters.vb
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
Imports System.IO
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Built-in filters for FileWatcher that are useful for correctly detecting changes on Office documents (currently Office 2016)
|
||||||
|
''' </summary>
|
||||||
|
Public Class FileWatcherFilters
|
||||||
|
''' <summary>
|
||||||
|
''' Base Filter that all filters must inherit from
|
||||||
|
''' Provides two functions that may be overridden and some useful file extension lists
|
||||||
|
''' </summary>
|
||||||
|
Public MustInherit Class BaseFileFilter
|
||||||
|
Public TempFiles As New List(Of String) From {".tmp", ""}
|
||||||
|
|
||||||
|
Public Overridable Function ShouldFilter(e As FileSystemEventArgs) As Boolean
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
Public Overridable Function ShouldRaiseSave(e As RenamedEventArgs) As Boolean
|
||||||
|
Return False
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Simple Filter that filters changes made on temporary files
|
||||||
|
''' </summary>
|
||||||
|
Public Class TempFileFilter
|
||||||
|
Inherits BaseFileFilter
|
||||||
|
|
||||||
|
Public Overrides Function ShouldFilter(e As FileSystemEventArgs) As Boolean
|
||||||
|
Dim oFileInfo As New FileInfo(e.FullPath)
|
||||||
|
Return TempFiles.Contains(oFileInfo.Extension)
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
|
||||||
|
''' <summary>
|
||||||
|
''' Filter to detect changes on Office files
|
||||||
|
''' </summary>
|
||||||
|
Public Class OfficeFileFilter
|
||||||
|
Inherits BaseFileFilter
|
||||||
|
|
||||||
|
Public OfficeFiles As New List(Of String) From {".docx", ".pptx", ".xlsx"}
|
||||||
|
|
||||||
|
Public Overrides Function ShouldFilter(e As FileSystemEventArgs) As Boolean
|
||||||
|
Dim oFileInfo As New FileInfo(e.FullPath)
|
||||||
|
Return OfficeFiles.Contains(oFileInfo.Extension) And oFileInfo.Name.StartsWith("~")
|
||||||
|
End Function
|
||||||
|
|
||||||
|
Public Overrides Function ShouldRaiseSave(e As RenamedEventArgs) As Boolean
|
||||||
|
Dim oIsTransform = OfficeFiles.Any(Function(Extension As String)
|
||||||
|
Return e.OldName.EndsWith(Extension)
|
||||||
|
End Function)
|
||||||
|
|
||||||
|
' Check if it is renamed to a temp file
|
||||||
|
Dim oIsTempFile = TempFiles.Any(Function(Extension)
|
||||||
|
Return e.Name.EndsWith(Extension)
|
||||||
|
End Function)
|
||||||
|
|
||||||
|
|
||||||
|
Return oIsTransform And oIsTempFile
|
||||||
|
End Function
|
||||||
|
End Class
|
||||||
|
End Class
|
||||||
10
Filesystem/FileWatcherProperties.vb
Normal file
10
Filesystem/FileWatcherProperties.vb
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
Public Class FileWatcherProperties
|
||||||
|
Public Property CreatedAt As DateTime
|
||||||
|
Public Property ChangedAt As DateTime
|
||||||
|
Public ReadOnly Property HasChanged As Boolean
|
||||||
|
Public Sub New()
|
||||||
|
CreatedAt = DateTime.Now
|
||||||
|
ChangedAt = Nothing
|
||||||
|
HasChanged = False
|
||||||
|
End Sub
|
||||||
|
End Class
|
||||||
@ -81,6 +81,8 @@
|
|||||||
<Compile Include="File.vb" />
|
<Compile Include="File.vb" />
|
||||||
<Compile Include="FileContainerInner.vb" />
|
<Compile Include="FileContainerInner.vb" />
|
||||||
<Compile Include="FileWatcher.vb" />
|
<Compile Include="FileWatcher.vb" />
|
||||||
|
<Compile Include="FileWatcherFilters.vb" />
|
||||||
|
<Compile Include="FileWatcherProperties.vb" />
|
||||||
<Compile Include="My Project\AssemblyInfo.vb" />
|
<Compile Include="My Project\AssemblyInfo.vb" />
|
||||||
<Compile Include="My Project\Application.Designer.vb">
|
<Compile Include="My Project\Application.Designer.vb">
|
||||||
<AutoGen>True</AutoGen>
|
<AutoGen>True</AutoGen>
|
||||||
|
|||||||
@ -1,30 +1,37 @@
|
|||||||
Imports System.ComponentModel
|
Imports System.ComponentModel
|
||||||
Imports System.IO
|
Imports System.IO
|
||||||
Imports DigitalData.Modules.Filesystem
|
Imports DigitalData.Modules.Filesystem
|
||||||
|
Imports DigitalData.Modules.Filesystem.FileWatcherFilters
|
||||||
Imports DigitalData.Modules.Logging
|
Imports DigitalData.Modules.Logging
|
||||||
|
|
||||||
Public Class FolderWatcher
|
Public Class FolderWatcher
|
||||||
|
|
||||||
Private _LogConfig As LogConfig
|
Private _LogConfig As LogConfig
|
||||||
|
Private _Logger As Logger
|
||||||
Private _Watcher As FileWatcher
|
Private _Watcher As FileWatcher
|
||||||
|
|
||||||
Public Sub FileCreated(_sender As Object, _e As FileSystemEventArgs)
|
<STAThread()>
|
||||||
ListBox1.Items.Add($"File created: {_e.FullPath}")
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Public Sub FileChanged(_sender As Object, _e As FileSystemEventArgs)
|
|
||||||
ListBox1.Items.Add($"File changed: {_e.FullPath}")
|
|
||||||
End Sub
|
|
||||||
|
|
||||||
Private Sub FolderWatcher_Load(sender As Object, e As EventArgs) Handles Me.Load
|
Private Sub FolderWatcher_Load(sender As Object, e As EventArgs) Handles Me.Load
|
||||||
_LogConfig = New LogConfig(LogConfig.PathType.CurrentDirectory, Nothing, "MAIN")
|
_LogConfig = New LogConfig(LogConfig.PathType.CurrentDirectory, Nothing, "MAIN")
|
||||||
_Watcher = New FileWatcher(_LogConfig, "E:\Watcher")
|
_LogConfig.Debug = True
|
||||||
|
_Logger = _LogConfig.GetLogger()
|
||||||
|
Dim oFilters As New List(Of BaseFileFilter) From {
|
||||||
|
New TempFileFilter,
|
||||||
|
New OfficeFileFilter
|
||||||
|
}
|
||||||
|
_Watcher = New FileWatcher(_LogConfig, "E:\Watcher", oFilters)
|
||||||
|
|
||||||
_Watcher.Add("*.*")
|
_Watcher.Add("*.*")
|
||||||
|
|
||||||
|
AddHandler _Watcher.FileSaved, AddressOf HandleFileSaved
|
||||||
|
|
||||||
_Watcher.Start()
|
_Watcher.Start()
|
||||||
End Sub
|
End Sub
|
||||||
|
|
||||||
|
Private Sub HandleFileSaved(FullName As String, IsSpecial As Boolean)
|
||||||
|
_Logger.Info("{1}File Saved: {0}", FullName, IIf(IsSpecial, "Special ", ""))
|
||||||
|
End Sub
|
||||||
|
|
||||||
Private Sub FolderWatcher_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
Private Sub FolderWatcher_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing
|
||||||
_Watcher.Stop()
|
_Watcher.Stop()
|
||||||
End Sub
|
End Sub
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user