Search

Watching Folder Activity in VB .NET

0 views

Overview of Folder Monitoring in VB.NET

When building desktop tools that need to react instantly to changes on the file system - such as synchronizing data, updating UI elements, or triggering background processes - having a reliable way to detect those changes becomes essential. In the days of VB6 or earlier, developers had to dig into low‑level Windows API calls like ReadDirectoryChangesW or FileSystemEvent APIs, wrap them manually, and manage timers to keep the application responsive. That approach demanded a lot of boilerplate code and left room for bugs, especially around handling multiple concurrent events and ensuring thread safety.

With the advent of the .NET Framework, Microsoft added a suite of classes in the System.IO and System.Diagnostics namespaces that abstract those complexities. At the heart of this functionality is the FileSystemWatcher class. It watches a specified directory and can raise a handful of events - Created, Changed, Deleted, Renamed, and Error - whenever a file or subdirectory is modified. The class is lightweight, supports filtering by file name or extension, and can even monitor entire sub‑trees of directories with a single instance.

Because FileSystemWatcher handles the underlying Windows file change notifications internally, you write less code and get a cleaner, more maintainable solution. You can plug the watcher into a Windows Forms application, WPF, or a console service and start receiving events with a few lines of code. In this guide we’ll walk through a practical example that demonstrates how to set up a simple Windows Forms app, configure the watcher, and handle the events in a user‑friendly way. By the end of the walkthrough you’ll see how quickly and safely you can create an application that reacts to real‑time file system changes.

Before diving into the code, it’s worth noting that the watcher works only on Windows platforms and requires a .NET runtime. It can monitor local drives, network shares, and UNC paths, but it does not support removable media such as CD‑ROMs. Also, the watcher relies on the operating system’s change‑notification service, so certain file operations - like bulk copies or antivirus scans - might generate multiple events or occasional spurious notifications. The example below shows how to handle the core events reliably, but you can extend it to manage error conditions and debouncing logic as needed.

In summary, FileSystemWatcher lets you focus on what you want to do when a file changes instead of how to detect that change. It’s the building block for many modern desktop utilities, backup solutions, and even lightweight monitoring services that need to keep an eye on the file system.

Setting Up the Project and UI

Open Visual Studio and create a new Windows Forms Application. Give the project a clear name, such as WatchFolder, and click OK. Once the project skeleton appears, we’ll design a simple interface that lets users choose a folder to monitor, start and stop the watcher, and view a live log of file events.

From the toolbox, drag a TextBox onto the form and set its Name property to txtWatchPath. Resize it so it spans the width of the form and add a Button next to it named btnStartWatch with the caption Start Watching. Below that, place another Button called btnStop and set its text to Stop Watching. Initially disable the stop button, because there is nothing to stop yet.

The next element is a multi‑line, read‑only TextBox that will display the event log. Name it txtFolderActivity, set Multiline to True, ScrollBars to Both, and ReadOnly to True. Arrange it below the buttons, making sure it has enough height to show a few dozen lines of output. This layout keeps the form tidy while providing all the controls needed for basic interaction.

To aid users, add a Label next to the folder path box that says Folder to monitor:. If you want to let users browse for a folder instead of typing the path manually, you can wire up a FolderBrowserDialog to the start button; for the purposes of this example, however, a simple text entry will suffice.

At this point you should have a form that looks roughly like this: a path entry, start/stop buttons, and an activity log area. You can test the layout by running the application, but the form won’t do anything yet because we haven’t added any code. Next we’ll add the logic that turns this UI into a working folder monitor.

Implementing FileSystemWatcher: Code Walkthrough

First, bring the necessary namespaces into scope. Above the class declaration, insert:

Prompt
Imports System.IO</p> <p>Imports System.Diagnostics

These imports give you access to the FileSystemWatcher class and related types. Next, declare a module‑level variable that will hold our watcher instance:

Prompt
Public watchFolder As FileSystemWatcher

We’ll create and configure this watcher inside the btnStartWatch_Click event handler. The handler starts by initializing a new FileSystemWatcher object:

Prompt
watchFolder = New FileSystemWatcher()

Set the path to the folder entered by the user:

Prompt
watchFolder.Path = txtWatchPath.Text

Define what kinds of changes you want to track. The NotifyFilter property is a bit‑mask, so you combine flags with the Or operator. In this example we’ll monitor directory name changes, file name changes, and attribute changes. The default includes last write, file name, and directory name, but we’ll be explicit to make the code clear:

Prompt
watchFolder.NotifyFilter = NotifyFilters.DirectoryName Or _</p> <p> NotifyFilters.FileName Or _</p> <p> NotifyFilters.Attributes

Attach handlers to the events that share the same signature. Created, Changed, and Deleted all use FileSystemEventArgs, so we can route them to a single method called LogChange:

Prompt
AddHandler watchFolder.Created, AddressOf LogChange</p> <p>AddHandler watchFolder.Changed, AddressOf LogChange</p> <p>AddHandler watchFolder.Deleted, AddressOf LogChange

The Renamed event has a different signature, so it needs its own handler, LogRename:

Prompt
AddHandler watchFolder.Renamed, AddressOf LogRename

Optionally, you can subscribe to the Error event to catch problems such as lost notifications. For a minimal example, we’ll skip that part, but be aware that in production code you should add error handling.

Finally, enable the watcher and update the UI:

Prompt
watchFolder.EnableRaisingEvents = True</p> <p>btnStartWatch.Enabled = False</p> <p>btnStop.Enabled = True

Now, implement the LogChange method. This method receives the event arguments and appends a descriptive line to the activity log. Because the ChangeType property tells us whether the event was a creation, modification, or deletion, we can handle each case with a simple conditional:

Prompt
Private Sub LogChange(ByVal source As Object, ByVal e As FileSystemEventArgs)</p> <p> Select Case e.ChangeType</p> <p> Case WatcherChangeTypes.Created</p> <p> txtFolderActivity.AppendText($"File {e.FullPath} created{vbCrLf}")</p> <p> Case WatcherChangeTypes.Changed</p> <p> txtFolderActivity.AppendText($"File {e.FullPath} modified{vbCrLf}")</p> <p> Case WatcherChangeTypes.Deleted</p> <p> txtFolderActivity.AppendText($"File {e.FullPath} deleted{vbCrLf}")</p> <p> End Select</p> <p>End Sub

The LogRename handler is similar but uses RenamedEventArgs to access the old and new names:

Prompt
Private Sub LogRename(ByVal source As Object, ByVal e As RenamedEventArgs)</p> <p> txtFolderActivity.AppendText($"File {e.OldFullPath} renamed to {e.FullPath}{vbCrLf}")</p> <p>End Sub

Finally, implement the stop button to disable the watcher and restore the UI state:

Prompt
Private Sub btnStop_Click(ByVal sender As Object, ByVal e As EventArgs)</p> <p> watchFolder.EnableRaisingEvents = False</p> <p> btnStartWatch.Enabled = True</p> <p> btnStop.Enabled = False</p> <p>End Sub

With these code snippets in place, your application is ready to start monitoring a folder and logging events as they happen. Compile and run the program to confirm the UI works; you’ll see that the Start Watching button disables itself while the Stop Watching button enables, reflecting the watcher’s state.

Running and Testing the Application

After building the project, launch the executable. The main form will appear with the path box, start/stop buttons, and the activity log. Type the full path of a folder you want to monitor - for example, C:\Temp - and click Start Watching. The start button will turn off and the stop button will turn on, indicating that the watcher has begun listening.

Open Windows Explorer and navigate to the folder you just entered. Create a new text file, edit it, rename it, or delete it. Each action should generate a line in the activity log that describes what happened. For instance, creating a file named test.txt will produce:

Prompt
File C:\Temp\test.txt created

Renaming that file to sample.txt will append:

Prompt
File C:\Temp\test.txt renamed to C:\Temp\sample.txt

Because the watcher operates on a background thread, the UI remains responsive; you can scroll the log or start/stop the watcher multiple times without the application hanging. If you stop the watcher and perform more file operations, nothing will be logged until you start watching again.

To validate error handling, try moving the folder to a location that the application no longer has access to, or change the path property to an invalid directory. While the basic example does not capture errors explicitly, you’ll notice that no new events are raised if the path is inaccessible. In a full‑featured app you’d subscribe to the Error event and display a message or attempt to re‑attach the watcher if the file system connection is lost.

Running through these scenarios gives you confidence that the FileSystemWatcher behaves predictably. It also highlights that a small amount of UI logic - enabling and disabling buttons, updating a text area - can turn a raw event source into a useful tool for end users.

Customizing and Extending the Watcher

While the example above shows a straightforward use case, the FileSystemWatcher offers several customization points that let you tailor its behavior to your specific needs. One of the most common adjustments is the Filter property, which limits the watcher to files that match a particular pattern. If you only care about text files, set watchFolder.Filter = ".txt". Leaving the filter as .* (the default) watches all file types.

Another useful setting is IncludeSubdirectories. By default, the watcher monitors only the directory specified by Path. Setting watchFolder.IncludeSubdirectories = True extends monitoring to every subfolder, turning the watcher into a tree monitor. Remember that watching many nested folders can increase the volume of events, so use this option judiciously when performance matters.

Because the watcher can monitor UNC paths, you can point it at network shares without issue. Just pass a UNC string - such as \\Server\Share\Folder - to the Path property. The underlying Windows notification system handles remote changes, so your application behaves the same whether the folder is local or remote.

Handling the Error event is vital for robust applications. The event provides a ErrorEventArgs that contains an exception object describing why notifications failed. A typical handler might look like this:

Prompt
Private Sub WatchFolder_Error(ByVal sender As Object, ByVal e As ErrorEventArgs)</p> <p> Dim ex = e.GetException()</p> <p> txtFolderActivity.AppendText($"Error: {ex.Message}{vbCrLf}")</p> <p> ' Optional: attempt to re‑enable watching after a delay</p> <p>End Sub

Adding debouncing logic is another common enhancement. Because certain file operations can raise multiple events in quick succession - especially when a large file is being written - you might want to coalesce those into a single log entry. One approach is to maintain a Dictionary(Of String, DateTime) that tracks the last time each file was reported. If a new event arrives within a short window (say 500 ms) for the same file, ignore it. This keeps the activity log concise without losing critical information.

For applications that need to trigger actions beyond logging - such as uploading a new file to a server, refreshing a data grid, or sending a notification - you can replace the body of the LogChange method with custom logic. Because the event handlers run on a background thread, be careful to marshal any UI updates back to the main thread using Invoke or a SynchronizationContext

Finally, keep in mind that FileSystemWatcher has a small buffer for pending events. If the buffer overflows, events are silently dropped. To mitigate this, keep the event handlers fast, avoid blocking operations, and consider increasing the InternalBufferSize property if you expect high‑volume traffic. However, larger buffers consume more memory and can still overflow under extreme load.

By exploring these options, you can adapt the basic example into a sophisticated monitoring tool that fits your workflow. Whether you’re building a lightweight utility for a single user or a service that runs on a server, the FileSystemWatcher provides a solid foundation for real‑time file system awareness.

Suggest a Correction

Found an error or have a suggestion? Let us know and we'll review it.

Share this article

Comments (0)

Please sign in to leave a comment.

No comments yet. Be the first to comment!

Related Articles