Version 1 of the VB.Net - FileSystemWatcher was pretty good. It had one basic flaw, If you are watching a location that disappears (for example a folder on a server that goes down), then the FileSystemWatcher will stop working. When the location reappears, the FileSystemWatcher does not recover.
To workaround this, you need a second object - like a timer, which checks to see if what the FileSystemWatcher is still available. If it is then great. If it isn’t then take the FileSystemWatcher offline until the location is restored.
PublicSubNew() 'use the timers default interval of 100 milliseconds and start the timer _myTimer.Start() EndSub
PublicSubNew(ByVal iNetworkWatchInterval As Int32, thePath AsString) 'check to see if the interval is a positive integer value and set it. If iNetworkWatchInterval > 0Then _myTimer.Interval = iNetworkWatchInterval Else'The user entered a _myTimer.Interval = 1000 EndIf _myTimer.Start() _thePath = thePath EndSub
PrivateSub _myTimer_Elapsed(ByVal sender AsObject, ByVal e As System.Timers.ElapsedEventArgs) Handles _myTimer.Elapsed Dim myFolder As DirectoryInfo
Try myFolder = New DirectoryInfo(_thePath)
IfNot _isNetworkUnavailable Then IfNot myFolder.Exists Then _isNetworkUnavailable = True RaiseEvent NetworkPathUnavailable("A network error has occured or the path does not exist anymore") EndIf Else If myFolder.Exists Then _isNetworkUnavailable = False RaiseEvent NetworkPathAvailable("The network or path has been restored") EndIf EndIf Catch ex As Exception Throw Finally myFolder = Nothing EndTry
EndSub
EndClass
As you can see, this class is a wrapper around the FileSystemWatcher, which checks the watched location and throws errors when that location is no longer available. The code demonstrated in version 1 would be supplemented to support some new events NetworkPathUnavailable and NetworkPathAvailable. Here’s what the resulting program looks like
PublicClass theMainV2 Inherits System.Windows.Forms.Form ' ' version 2 came from ' http://www.codeproject.com/Articles/15656/Advanced-FileSystemWatcher ' I moved portions into this project ' PrivateDelegateSub updatetextbox(ByVal newLabel AsString) PrivateWithEvents anAdvFileSystemWatcher As AdvancedFileSystemWatcher Private Watch4Changes AsBoolean = False
PrivateSub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Load
Dim cmdline AsString _ = Command() Dim cmd() AsString _ = cmdline.Split(" ")
Console.WriteLine("Directory Watch Utility") Console.WriteLine("Creates a log of files added, modified, created, deleted, or renamed for a specific directory") Console.WriteLine("") Console.WriteLine("Usage") Console.WriteLine(" DirWatch DirectoryToWatch LogFileName") Console.WriteLine("") If cmd.Length < 2Then End EndIf txtFolderToWatch.Text = cmd(0) txtCSVFileName.Text = cmd(1)
PrivateSub StartFileSystemWatcher() Try 'Create a new Advanced File System Watcher and set the network scan interval anAdvFileSystemWatcher = New AdvancedFileSystemWatcher(5000, txtFolderToWatch.Text)
'Add the handlers to handle the filesystemwatcher events AddHandler anAdvFileSystemWatcher.Created, AddressOf OnCreated AddHandler anAdvFileSystemWatcher.Changed, AddressOf OnChanged AddHandler anAdvFileSystemWatcher.Deleted, AddressOf Ondeleted AddHandler anAdvFileSystemWatcher.Renamed, AddressOf OnRenamed
Log(",,Dir Watcher Program now watching - " & txtFolderToWatch.Text) Catch ex As Exception Log(",,Error " & ex.GetBaseException.ToString) EndTry EndSub
PrivateSub StopFileSystemWatcher() Try anAdvFileSystemWatcher.EnableRaisingEvents = False Log(",,Dir Watcher Program no longer watching - " & txtFolderToWatch.Text) Catch ex As Exception Throw ex EndTry EndSub
PublicSub OnChanged(ByVal source AsObject, ByVal e As FileSystemEventArgs) If Watch4Changes Then Dim fullpath AsString = e.FullPath Dim filename AsString = Path.GetFileName(fullpath) Dim thepath AsString = Path.GetDirectoryName(fullpath)
PublicSub OnCreated(ByVal source AsObject, ByVal e As FileSystemEventArgs) Try Dim fullpath AsString = e.FullPath Dim filename AsString = Path.GetFileName(fullpath) Dim thepath AsString = Path.GetDirectoryName(fullpath)
Log(thepath & ", " & filename & ", created") Catch ex As Exception Throw ex EndTry
EndSub
PublicSub Ondeleted(ByVal source AsObject, ByVal e As FileSystemEventArgs) Try Dim fullpath AsString = e.FullPath Dim filename AsString = Path.GetFileName(fullpath) Dim thepath AsString = Path.GetDirectoryName(fullpath)
Log(thepath & ", " & filename & ", deleted") Catch ex As Exception Throw ex EndTry
EndSub
PublicSub OnRenamed(ByVal source AsObject, ByVal e As RenamedEventArgs) Try Dim fullpath AsString = e.OldName Dim filename AsString = Path.GetFileName(fullpath) Dim thepath AsString = Path.GetDirectoryName(fullpath)
Dim newfilename AsString = Path.GetFileName(e.Name) Log(thepath & ", " & filename & ", renamed to " & newfilename)
Catch ex As Exception Throw ex EndTry
EndSub
PrivateSub btnExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
Me.Close() Me.Dispose()
EndSub
PrivateSub anAdvFileSystemWatcher_NetworkPathAvailable(ByVal Message AsString) Handles anAdvFileSystemWatcher.NetworkPathAvailable Try 'Ok the network path is available now StartFileSystemWatcher() Catch ex As Exception Log(",,Error in NetworkPathAvailable - " & ex.GetBaseException.ToString) EndTry EndSub
PrivateSub anAdvFileSystemWatcher_NetworkPathUnavailable(ByVal Message AsString) Handles anAdvFileSystemWatcher.NetworkPathUnavailable Try 'There was a network error we need to destroy the filesystemwatcher object and try to recreate it. 'Send an email saying there is a netowrk error???? 'SendMail
'now we have to stop and kill the current filesystemwatcher. we will recreate it in the available event. StopFileSystemWatcher() anAdvFileSystemWatcher.Dispose()
Catch ex As Exception Throw ex EndTry EndSub
PublicSub Log(message AsString) If lblComputerName.Text.Length > 0Then message += ", " + lblComputerName.Text EndIf If lblUserName.Text.Length > 0Then message += ", " + lblUserName.Text EndIf Try Using sw As StreamWriter = File.AppendText(txtCSVFileName.Text) sw.WriteLine(DateTime.Now.ToString & ", " + message) EndUsing
Catch ex As Exception Console.WriteLine(DateTime.Now.ToString & ",, *** ERROR TRYING TO WRITE TO LOG - " & ex.Message) EndTry Console.WriteLine(DateTime.Now.ToString & ", " + message) EndSub
PrivateSub theMainV2_Closing(sender AsObject, e As CancelEventArgs) HandlesMe.Closing Log(",,Dir Watcher Program Ending - " & txtFolderToWatch.Text) EndSub EndClass
Another sample
The FileSystemWatcher class is used to create a function that watches activities being performed on files sitting in a folder. When running it will throw an event whenever a file is added, changed, deleted, or renamed.
Actually I found several suprisingly good websites.
Note: I created a form, and placed the code within the form. I did this because If I created a main() routine, it would execute, and then terminate and the FileSystemWatcher would not be running. By creating the form I know that the FileSystemWatcher is functioning because the window is open.
On the form I added a textbox control:
A directory to watch named ‘txtDir’. it is populated with the folder being watched
Here is a stripped down version of the code behind the form
Imports System Imports System.IO Imports System.Diagnostics Imports System.Windows.Forms
PublicClass theMain Public watchfolder As FileSystemWatcher
PrivateSub theMain_Load(sender AsObject, e As EventArgs) HandlesMyBase.Load Dim cmdline AsString _ = Command() Dim cmd() AsString _ = cmdline.Split(" ")
Console.WriteLine("Directory Watch Utility") Console.WriteLine("Creates a log of files added, modified, created, " _ & "deleted, or renamed for a specific directory") Console.WriteLine("") Console.WriteLine("Usage") Console.WriteLine(" DirWatch DirectoryToWatch ") Console.WriteLine("") If cmd.Length < 2Then End EndIf txtDir.Text = cmd(0)