Click here to Skip to main content
Click here to Skip to main content

Track File Activites

, 12 Feb 2013 GPL3
Rate this:
Please Sign up or sign in to vote.
It helps to track/monitor file activites using FileSystemWatcher and maintains log, which can be viewed using various filter options.
Track File Activites

Introduction

This application will demonstrate how to effectively use FileSystemWatcher. The application is flexible enough for user configuration. The user needs to provide the track path which s/he wants to keep a track of and provide another work path where log file will be maintained daily. Folders will be created for each day and log will be maintained. This will give user the flexibility to view previous day's log without any fuzz. Note that once this path has been defined, it will be stored in System Registry, so the user does not have to feed in the path every time s/he opens the application, it will be automatically retrieved from registry. The user can choose the option for tracking subfolders or not. S/he can filter using various options, like "*.*, *win.*, a*b.c* and so on...". Notify filter can also be configured based on user's need, like "FileName, DirectoryName, Attributes, Size, LastWrite, LastAccess, CreationTime, Security".

Track File Activities Log

Track File Activites Log

This window helps to view the log that has been created by TrackFileActivity for each day. Usually the generated log for each day is huge and it is a very tedious job to view all these logs. The user has the option to filter the data based on Events, Path, Time. Event can be selected for "Created", "Changed", "Deleted", and "Renamed". Path can be any string which is not case sensitive. Time can filter between start time and end time. The user also has an option for defining Auto Refresh Interval which will refresh the log view based on the filter at the mentioned interval automatically. If s/he wants to manually refresh the log view, then click on Manual Refresh button. The user has the option to click on the column of list view to sort the log/data in ascending or descending order. Each log in the Log View will be grouped by "Create", "Rename", "Delete", and "Change" which will be denoted by colors. By default, the log view will be for present date, but the user has the option to select previous date log files and view them as well. For simplicity, Track File Activities Log window can be opened for only one instance at any given time. That means the user cannot open multiple windows for Track File Activities Log. This will give the learner a good code to handle these situations using user32.dll.

Notify Icon

Notify Icon

Notify Icon can be double clicked to open TrackFileActivities at any instance. The user has the option to right click and open TrackFileActivities options, Track File Activities Log or exit the application. While exiting TrackFileActivities, it will ask for confirmation for exiting the application.

Using the Code

SendMessage

This code demonstrates how to implement USER32.dll and open any window for a single instance at any given time.

//Declare global variable
private int hwdfrmTrackLog;

//Import this function
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);

//Display frmTrackLog if the form is not already opened
if (hwdfrmTrackLog == -1)
{
   frmTrackLog objfrmTrackLog = new frmTrackLog(strWorkPath);
   objfrmTrackLog.Disposed += new EventHandler(frmTrackLog_Disposed);
   hwdfrmTrackLog = objfrmTrackLog.Handle.ToInt32();
   objfrmTrackLog.Show();
}        

public void frmTrackLog_Disposed(object sender, EventArgs e)
{
   //When the form is disposed, set the handle back
   hwdfrmTrackLog = -1;
}

Registry

This code demonstrates how to read/write values in System Registry Key.

using Microsoft.Win32;

//Read from Registry Key if value exists
RegistryKey rk = Registry.LocalMachine;
RegistryKey rkOpenTrack = rk.OpenSubKey("SOFTWARE\\" + 
        "TrackFileActivitesSumit\\TrackPath");
if (rkOpenTrack != null)
{
   txtSetPath.Text = rkOpenTrack.GetValue("Path").ToString();
}

//Write value to Registry Key
RegistryKey rk = Registry.LocalMachine;
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
   txtSetPath.Text = folderBrowserDialog.SelectedPath;
   RegistryKey rkCreate = rk.CreateSubKey("SOFTWARE\\" + 
        "TrackFileActivitesSumit\\TrackPath");
   rkCreate.SetValue("Path", txtSetPath.Text);
}

btnStartTracking_Click

This code demonstrates how to set filters and notify filters and other parameters for FileSystemWatcher. It also checks and sets other controls accordingly.

private void btnStartTracking_Click(object sender, EventArgs e)
{
  try
  {
     if ((txtSetPath.Text.Length != 0) && (txtWorkPath.Text.Length != 0))
     {
         notifyIcon.Text = "Track File Activites [running]";
         btnStartTracking.Enabled = false;
         btnStopTracking.Enabled = true;

         btnSetPath.Enabled = false;
         btnWorkPath.Enabled = false;
         cmbFilters.Enabled = false;
         chkIncludeSubdirectories.Enabled = false;
         gbNotifyFilter.Enabled = false;

         this.fileSystemWatcher.EnableRaisingEvents = false;
         if (chkAttributes.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.Attributes;
         }
         if (chkCreationTime.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.CreationTime;
         }
         if (chkDirectoryName.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
            fileSystemWatcher.NotifyFilter | NotifyFilters.DirectoryName;
         }
         if (chkFileName.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.FileName;
         }
         if (chkLastAccess.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.LastAccess;
         }
         if (chkLastWrite.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.LastWrite;
         }
         if (chkSecurity.Checked == true)
         {
             fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.Security;
         }
         if (chkSize.Checked == true)
         {
              fileSystemWatcher.NotifyFilter = 
                fileSystemWatcher.NotifyFilter | NotifyFilters.Size;
         }

         fileSystemWatcher.Path = txtSetPath.Text;
         fileSystemWatcher.Filter = cmbFilters.Text;
         fileSystemWatcher.IncludeSubdirectories = chkIncludeSubdirectories.Checked;
         fileSystemWatcher.EnableRaisingEvents = true;
     }
     else
     {
          MessageBox.Show("Either of the path is not defined. 
    Please define the path for Track File Activities and Working Path for Log.", 
        "Please define Tracking and
    Working path ...", MessageBoxButtons.OK, MessageBoxIcon.Information);
      }
   }
   catch (ArgumentException ae)
   {
       MessageBox.Show(ae.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
   }
   catch (Exception ee)
   {
       MessageBox.Show(ee.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
   }
}

fileSystemWatcher_Renamed

This code demonstrates how to implement events for FileSystemWatcher and append in a log file. It demonstrates for Rename event which is the same as other events, namely "Create", "Delete", and "Change".

private void fileSystemWatcher_Renamed(object sender, System.IO.RenamedEventArgs e)
{
   StreamWriter sw = File.AppendText(strWorkPath);
   sw.WriteLine(e.ChangeType + "|" + e.OldFullPath + " to " + e.FullPath + 
        "|" + DateTime.Now.ToLongTimeString());
   sw.Flush();
   sw.Close();
}

DisplayLogInListView

This code demonstrates how to implement read log file, apply filter to these data and assign color to each log grouping by "Create", "Rename", "Delete", and "Change".

public void DisplayLogInListView()
{
    try
    {
        timer.Enabled = false;

        if (!File.Exists(txtLogPath.Text.Replace("TrackFileActivities.log", "") +
            "Copy of TrackFileActivities.log"))
        {
            File.Copy(txtLogPath.Text, 
                txtLogPath.Text.Replace("TrackFileActivities.log", "") + 
                    "Copy of TrackFileActivities.log");
        }
        else
        {
            File.Delete(txtLogPath.Text.Replace("TrackFileActivities.log", "") +
                "Copy of TrackFileActivities.log");
            File.Copy(txtLogPath.Text, 
                txtLogPath.Text.Replace("TrackFileActivities.log", "") +
                    "Copy of TrackFileActivities.log");
        }

        listViewLog.Items.Clear();
        Match matchRegEx;
        ListViewItem lvItem;
        string strReadLog = "";
        string[] strReadLogColl;
        TextReader tr = new StreamReader
            (txtLogPath.Text.Replace("TrackFileActivities.log", "") +
                "Copy of TrackFileActivities.log");
        while ((strReadLog = tr.ReadLine()) != null)
        {
            bool boolFlag = false;
            strReadLogColl = strReadLog.Split('|');
            if ((chkCreated.Checked == true) && (strReadLogColl[0] == "Created"))
            {
                matchRegEx = Regex.Match(strReadLogColl[1], txtPath.Text, 
                    RegexOptions.IgnoreCase);
                if (matchRegEx.Success)
                {
                    DateTime dtCompStartTime = Convert.ToDateTime
                        (dtStartTime.Value.ToShortDateString() + " " +
                            strReadLogColl[2]);
                    DateTime dtCompEndTime = Convert.ToDateTime
                        (dtEndTime.Value.ToShortDateString() + " " +
                            strReadLogColl[2]);
                    if ((dtCompStartTime >= dtStartTime.Value) && 
                        (dtCompEndTime <= dtEndTime.Value))
                    {
                        boolFlag = true;
                    }
                }
            }
            if ((chkDeleted.Checked == true) && (strReadLogColl[0] == "Deleted"))
            {
                matchRegEx = Regex.Match(strReadLogColl[1], 
                txtPath.Text, RegexOptions.IgnoreCase);
                if (matchRegEx.Success)
                {
                    DateTime dtCompStartTime = Convert.ToDateTime
                    (dtStartTime.Value.ToShortDateString() + " " +
                    strReadLogColl[2]);
                    DateTime dtCompEndTime = Convert.ToDateTime
                    (dtEndTime.Value.ToShortDateString() + " " +
                    strReadLogColl[2]);
                    if ((dtCompStartTime >= dtStartTime.Value) && 
                    (dtCompEndTime <= dtEndTime.Value))
                    {
                        boolFlag = true;
                    }
                }
            }
            if ((chkRenamed.Checked == true) && (strReadLogColl[0] == "Renamed"))
            {
                matchRegEx = Regex.Match(strReadLogColl[1], txtPath.Text, 
                    RegexOptions.IgnoreCase);
                if (matchRegEx.Success)
                {
                    DateTime dtCompStartTime = Convert.ToDateTime
                    (dtStartTime.Value.ToShortDateString() + " " +
                    strReadLogColl[2]);
                    DateTime dtCompEndTime = Convert.ToDateTime
                    (dtEndTime.Value.ToShortDateString() + " " +
                    strReadLogColl[2]);
                    if ((dtCompStartTime >= dtStartTime.Value) && 
                    (dtCompEndTime <= dtEndTime.Value))
                    {
                        boolFlag = true;
                    }
                }
            }
            if ((chkChanged.Checked == true) && (strReadLogColl[0] == "Changed"))
            {
                matchRegEx = Regex.Match(strReadLogColl[1], 
                    txtPath.Text, RegexOptions.IgnoreCase);
                if (matchRegEx.Success)
                {
                    DateTime dtCompStartTime = Convert.ToDateTime
                    (dtStartTime.Value.ToShortDateString() + " " +
                    strReadLogColl[2]);
                    DateTime dtCompEndTime = Convert.ToDateTime
                    (dtEndTime.Value.ToShortDateString() + " " +
                    strReadLogColl[2]);
                    if ((dtCompStartTime >= dtStartTime.Value) && 
                    (dtCompEndTime <= dtEndTime.Value))
                    {
                        boolFlag = true;
                    }
                }
            }
            lvItem = new ListViewItem(strReadLogColl[0]);
            lvItem.SubItems.Add(strReadLogColl[1]);
            lvItem.SubItems.Add(strReadLogColl[2]);
            if (strReadLogColl[0] == "Created")
            {
                lvItem.ForeColor = Color.Blue;
            }
            else if (strReadLogColl[0] == "Changed")
            {
                lvItem.ForeColor = Color.Brown;
            }
            else if (strReadLogColl[0] == "Deleted")
            {
                lvItem.ForeColor = Color.Red;
            }
            else if (strReadLogColl[0] == "Renamed")
            {
                lvItem.ForeColor = Color.Green;
            }
            if (boolFlag == true)
            {
                listViewLog.Items.Add(lvItem);
            }
        }
        tr.Close();
        File.Delete(txtLogPath.Text.Replace("TrackFileActivities.log", "") + 
            "Copy of TrackFileActivities.log");
        timer.Enabled = true;
        if (listViewLog.Items.Count > 0)
        {
            listViewLog.EnsureVisible(listViewLog.Items.Count - 1);
            listViewLog.Items[listViewLog.Items.Count - 1].Selected = true;
        }
    }
    catch (Exception ee)
    {
        MessageBox.Show(ee.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Points of Interest

One thing to note is you cannot change the notify filter until and unless you set:

fileSystemWatcher.EnableRaisingEvents = false;

If somebody feels that if the user wants to open the Track File Activities Log window for a second instance, then s/he can do so by sending:

SendMessage(hwdMyForm, 0x0112, 0xF060, 0);

This will dispose the first window and open a new window for the second instance.

Good luck and have a nice day!

History

  • 24th July, 2008: Initial post
  • 13th Feb, 2013: Uploaded code and executable file which was broken

This is the first version. I will be happy if I can add more functionalities and enhancements to the existing one.

License

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

Share

About the Author

Biswas, Sumit
Tester / Quality Assurance
India India
I am a Performance Engineer, but I like programming. i don't do it as a specialty, but because i love it. anyone who supports source code sharing on the same plane as me.
Anyone who wants to learn more about me can feel free to contact me. Meanwhile, i'd appreciate your feedback. Get in touch sumitsushil@gmail.com
 
* If this article is helpful, please give reputation points.
* Don't forget to tip the waiter with your appreciation.

Comments and Discussions

 
GeneralMy vote of 5 PinmemberJerome Vibert24-Apr-13 22:46 
QuestionThe only issue I see ... PinmemberGarth J Lancaster12-Feb-13 22:47 
Bug404 Pinmemberasd0z20-Aug-12 16:41 
GeneralRe: 404 PinmemberBiswas, Sumit12-Feb-13 23:12 
QuestionLogging the username who raised the events ? PinmemberKennethEhmsen22-Jan-12 23:51 
AnswerRe: Logging the username who raised the events ? PinmemberBiswas, Sumit12-Feb-12 17:51 
GeneralMy vote of 5 Pinmemberyamilovesea4-Nov-10 21:43 
GeneralFew things... PinmemberSelvin28-Jul-08 0:07 
GeneralReally Nice Post Pinmembermlpnko27-Jul-08 18:09 
GeneralInteresting Pinmembermerlin98125-Jul-08 4:22 
GeneralRe: Interesting PinmemberBiswas, Sumit27-Jul-08 17:46 
GeneralPlease fix Pinmemberpeterchen24-Jul-08 22:41 
GeneralRe: Please fix PinmemberBiswas, Sumit27-Jul-08 17:52 
GeneralRe: Please fix Pinmemberpeterchen27-Jul-08 19:48 
GeneralRe: Please fix PinmemberBiswas, Sumit28-Jul-08 1:24 

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

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

| Advertise | Privacy | Mobile
Web04 | 2.8.141015.1 | Last Updated 13 Feb 2013
Article Copyright 2008 by Biswas, Sumit
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid