Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / C#

Watching Folder Activity in C# .NET

Rate me:
Please Sign up or sign in to vote.
3.11/5 (19 votes)
2 Jul 2008GPL32 min read 153.7K   4.6K   55   10
How to monitor a folder's activity with delegates and events threadsafe
Image 1

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:

C#
[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.

C#
// 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.

C#
/// <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...

C#
_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

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Sweden Sweden
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionHelp about When files created, I wanna move them another directory Pin
cllunlu1-Dec-14 4:01
cllunlu1-Dec-14 4:01 
GeneralMy vote of 5 Pin
rama charan15-Mar-12 22:13
rama charan15-Mar-12 22:13 
Questionhow to watching two folders? Pin
yuyejian12-Jun-10 22:10
yuyejian12-Jun-10 22:10 
GeneralThank you for this article Pin
TonyHenrique27-Mar-10 10:11
TonyHenrique27-Mar-10 10:11 
GeneralEmail the results Pin
Leigh Turner14-Apr-09 21:47
Leigh Turner14-Apr-09 21:47 
GeneralRe: Email the results Pin
MrMahjong15-Apr-09 1:46
MrMahjong15-Apr-09 1:46 
Well, you could as soon as the event triggers start a sub-routine to send an e-mail with the message. sumthing like this?

// Mail refrences
using System.Net;
using System.Net.Mail;
using System.IO;

namespace WAB.Tools
{
    public static class SMTP
    {
        private static string s_CREDENTIAL_Username = "username";
        private static string s_CREDENTIAL_Password = "password";

        private static string s_SMTP_Server = "smtp.company.com";
        private static int s_SMTP_Port = 587; // Standard
        private static bool b_SMTP_EnableSSL = true; // If SSL needed.

        // could be private aswell.
        internal static bool SendMail(MailMessage mm)
        {
            SmtpClient smtp = new SmtpClient(s_SMTP_Server, s_SMTP_Port);

            try
            {
                smtp.Credentials = new NetworkCredential(s_CREDENTIAL_Username, s_CREDENTIAL_Password);
                smtp.EnableSsl = b_SMTP_EnableSSL;
                smtp.Send(mm);
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        public static void Send_Mail(string Body)
        {
            MailAddress ma_SENDER = new MailAddress("info@company.com", "Company Name");
            MailAddress ma_TO = new MailAddress("send-to@someone.com");
            MailAddress ma_REPLY_TO = new MailAddress("reply-to@company.com");

            MailMessage m = new MailMessage(ma_SENDER, ma_TO);
            m.Subject = "Folder changed sum data ;)";

            StringBuilder sb = new StringBuilder();

            // This is the main message
            sb.Append(Body);

            m.IsBodyHtml = true;
            m.Body = sb.ToString();
            m.Sender = ma_SENDER;
            m.From = ma_SENDER;
            m.ReplyTo = ma_REPLY_TO;

            m.Priority = MailPriority.High;

            try { SendMail(m); }
            catch (Exception e) { throw e; }
        }

GeneralRe: Email the results Pin
Leigh Turner15-Apr-09 1:55
Leigh Turner15-Apr-09 1:55 
GeneralMy vote of 2 Pin
Gilad Kapelushnik29-Mar-09 22:05
Gilad Kapelushnik29-Mar-09 22:05 
GeneralThe point. Pin
MrMahjong21-Apr-08 22:18
MrMahjong21-Apr-08 22:18 
QuestionWhat's the point? Pin
Shog921-Apr-08 13:13
sitebuilderShog921-Apr-08 13:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.