Windows Service - FileSystemWatcher example code

I've needed a piece of code like this for some time.

Recently I was asked to write an application that would watch a directory and respond to files that were saved there. We'd need to pick them up, process them, and then move them to a 'done' folder. Standard Dyn Developer stuff.

Normally, I'd write a console application and schedule it with SQL scheduler to sweep the folder every x minutes.

At some point I became aware of the System.IO.FileSystemWatcher class. The FileSystemWatcher class 'Listens to the file system change notifications and raises events when a directory, or file in a directory, changes'. Cool, right? The example below is a complete Windows Service application that uses the FileSystemWatcher class to monitor a directory and to respond to files that are saved in that directory.

The paragraphs below are from the MSDN remarks for the FileSystemWatcher class:

Use FileSystemWatcher to watch for changes in a specified directory. You can watch for changes in files and subdirectories of the specified directory. You can create a component to watch files on a local computer, a network drive, or a remote computer.

To watch for changes in all files, set the Filter property to an empty string ("") or use wildcards ("*.*"). To watch a specific file, set the Filter property to the file name. For example, to watch for changes in the file MyDoc.txt, set the Filter property to "MyDoc.txt". You can also watch for changes in a certain type of file. For example, to watch for changes in text files, set the Filter property to "*.txt".

There are several types of changes you can watch for in a directory or file. For example, you can watch for changes in Attributes, the LastWrite date and time, or the Size of files or directories. This is done by setting the NotifyFilter property to one of the NotifyFilters values. For more information on the type of changes you can watch, see NotifyFilters.

You can watch for renaming, deletion, or creation of files or directories. For example, to watch for renaming of text files, set the Filter property to "*.txt" and call the WaitForChanged method with a Renamed specified for its parameter.

The Windows operating system notifies your component of file changes in a buffer created by the FileSystemWatcher. If there are many changes in a short time, the buffer can overflow. This causes the component to lose track of changes in the directory, and it will only provide blanket notification. Increasing the size of the buffer with the InternalBufferSize property is expensive, as it comes from non-paged memory that cannot be swapped out to disk, so keep the buffer as small yet large enough to not miss any file change events. To avoid a buffer overflow, use the NotifyFilter and IncludeSubdirectories properties so you can filter out unwanted change notifications.

Imports System.IO
Imports System.Xml
 
Public Class Service1
    Public watcher As System.IO.FileSystemWatcher
 
    Protected Overrides Sub OnStart(ByVal args() As String)
        Try
            'this method is found in our standard error handling code here: http://dyndeveloper.com/thread.aspx?Threadid=1261
            WriteToEventLog("The eConnect Service has started"EventLogEntryType.Information)
 
            'get the directory that we want to watch from the configuration file
            Dim strDirectory As String = System.Configuration.ConfigurationManager.AppSettings("RootDirectory")
 
            ' Create a new FileSystemWatcher and set its properties.
            watcher = New FileSystemWatcher
            watcher.Path = strDirectory
 
            ' Watch for new files
            watcher.Filter = "*.xml"
 
            ' Add event handlers.
            AddHandler watcher.Created, AddressOf OnChanged
 
            ' Begin watching.
            watcher.EnableRaisingEvents = True
 
        Catch ex As Exception
            'standard error handling code found here: http://dyndeveloper.com/thread.aspx?Threadid=1261
            globalErrorHandler(ex)
        End Try
    End Sub
 
    Protected Overrides Sub OnStop()
        'this method is found in our standard error handling code here: http://dyndeveloper.com/thread.aspx?Threadid=1261
        WriteToEventLog("The eConnect Service has stopped"EventLogEntryType.Information)
    End Sub
 
 
    ' Define the event handlers.
    Private Shared Sub OnChanged(ByVal source As ObjectByVal e As FileSystemEventArgs)
        ' Specify what is done when a file is created.
        Dim xdoc As New XmlDocument
 
        'get a reference to the root directory, and two sub directories
        Dim strDirectory As String = System.Configuration.ConfigurationManager.AppSettings("RootDirectory")
        Dim strDirectoryDone As String = Path.Combine(strDirectory, "done")
        Dim strDirectoryError As String = Path.Combine(strDirectory, "error")
 
        'to make debugging easier, we always put the main code in a class so that it can be called by this service
        'or a Winform debugging application
        Dim o As New eConnect11Lib.FileHandler
 
        'create the two subdirectories
        If Not Directory.Exists(strDirectoryDone) Then
            Directory.CreateDirectory(strDirectoryDone)
        End If
        If Not Directory.Exists(strDirectoryError) Then
            Directory.CreateDirectory(strDirectoryError)
        End If
 
        'loop through all the files in the directory. 
        Dim oFiles As New DirectoryInfo(strDirectory)
        For Each oFile As FileInfo In oFiles.GetFiles("*.xml")
            Try
                'this method is found in our standard error handling code here: http://dyndeveloper.com/thread.aspx?Threadid=1261
                WriteToEventLog("Processing file " & oFile.Name, EventLogEntryType.Information)
 
                'load the document from disk into an XmlDocument
                xdoc.Load(oFile.FullName)
 
                'process the document in our external class
                o.ProcessDocument(xdoc.OuterXml)
 
                'if no errors occurred, move the file to the 'done' folder
                If File.Exists(Path.Combine(strDirectoryDone, oFile.Name)) Then
                    File.Delete(Path.Combine(strDirectoryDone, oFile.Name))
                End If
 
                File.Move(oFile.FullName, Path.Combine(strDirectoryDone, oFile.Name))
 
                'this method is found in our standard error handling code here: http://dyndeveloper.com/thread.aspx?Threadid=1261
                WriteToEventLog("Processing complete on file " & oFile.Name, EventLogEntryType.Information)
            Catch ex As Exception
                'an error occurred
 
                'this method is found in our standard error handling code here: http://dyndeveloper.com/thread.aspx?Threadid=1261
                WriteToEventLog("Processing errors"EventLogEntryType.Information)
 
                'move the file to the 'error' sub directory
                If File.Exists(Path.Combine(strDirectoryError, oFile.Name)) Then
                    File.Delete(Path.Combine(strDirectoryError, oFile.Name))
                End If
 
                File.Move(oFile.FullName, Path.Combine(strDirectoryError, oFile.Name))
 
                'this method is found in our standard error handling code here: http://dyndeveloper.com/thread.aspx?Threadid=1261
                'we gather all the data that we can, email the error, and write it to the event log
                globalErrorHandler(ex, "File: " & oFile.Name)
            End Try
        Next 'xml document
    End Sub
 
End Class

RealWorldCode gives developers practical, real‑world solutions with clean, working code — no fluff, no theory, just answers.
Links
Home
Knowledge Areas
Sitemap
Contact
Et cetera
Privacy Policy
Terms and Conditions
Cookie Preferences