Watching Folder Activity in C# .NET
How to monitor a folder's activity with delegates and events threadsafe

Update 2008-07-03 - Vista Fix
If you are having trouble accessing the folder with permissions, you could always force UAC to elevate your securitygrade.
Use:
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
It's under System.Security.Permissions
namespace.
Introduction
I'm currently working on a project that needed to watch a folder's activity and trigger event in my application. So I started to search The Code Project and found out that the only code that existed was from 2003, and it did not even work (maybe because I'm on Vista?). Either ways, there were threads crossing other threads and fuzzy commenting, so I decided to clean it up. It's originally based on Jayesh Jaine's work who did this in VB.NET back in 2002. Then in 2003 Gerald Nelson picked it up, translated it to C#, but somehow he did not finish it. It was not threadsafe, blah blah blah...
Alright, let's continue.
Using the Code
It's really easy to use and I commented it well. As you can see below, we first declare _watchFolder
as a FileSystemWatcher
from the System.IO
.
We just set the parameters to what we want to listen to and then connect the eventhandlers to some function.
// System.IO
FileSystemWatcher _watchFolder = new FileSystemWatcher();
private void startActivityMonitoring(string sPath)
{
// This is the path we want to monitor
_watchFolder.Path = sPath;
// Make sure you use the OR on each Filter because we need to monitor
// all of those activities
_watchFolder.NotifyFilter = System.IO.NotifyFilters.DirectoryName;
_watchFolder.NotifyFilter =
_watchFolder.NotifyFilter | System.IO.NotifyFilters.FileName;
_watchFolder.NotifyFilter =
_watchFolder.NotifyFilter | System.IO.NotifyFilters.Attributes;
// Now hook the triggers(events) to our handler (eventRaised)
_watchFolder.Changed += new FileSystemEventHandler(eventRaised);
_watchFolder.Created += new FileSystemEventHandler(eventRaised);
_watchFolder.Deleted += new FileSystemEventHandler(eventRaised);
// Occurs when a file or directory is renamed in the specific path
_watchFolder.Renamed += new System.IO.RenamedEventHandler(eventRenameRaised);
// And at last.. We connect our EventHandles to the system API (that is all
// wrapped up in System.IO)
try
{
_watchFolder.EnableRaisingEvents = true;
}
catch (ArgumentException)
{
abortAcitivityMonitoring();
}
}
Just a quick look at the function that handles the events.
/// <summary>
/// Triggered when an event is raised from the folder activity monitoring.
/// All types exists in System.IO
/// </summary>
/// <param name="sender"></param>
/// <param name="e">containing all data send from the event that got executed.</param>
private void eventRaised(object sender, System.IO.FileSystemEventArgs e)
{
switch (e.ChangeType)
{
case WatcherChangeTypes.Changed:
TS_AddLogText(string.Format("File {0} has been modified\r\n", e.FullPath));
break;
case WatcherChangeTypes.Created:
TS_AddLogText(string.Format("File {0} has been created\r\n", e.FullPath));
break;
case WatcherChangeTypes.Deleted:
TS_AddLogText(string.Format("File {0} has been deleted\r\n", e.FullPath));
break;
default: // Another action
break;
}
}
Points of Interest
One thing that I discovered while doing this is that when creating a file in the folder you are monitoring, windows is modifying this file twice.
Another thing is when an event is raised, the event is called from another thread. Now this causes it to crash if we don't make any control or component we want to access that was created on other threads to threadsafe. There is an example in the source code on how to do this.
Tip: Don't forget to set...
_watchFolder.EnableRaisingEvents = false;
... when you want it to stop listening. If you assign the listeners twice, it will trigger both events. Happy coding, my friends!
History
- 21st April, 2008: First release
- 3rd July, 2008: Vista fix