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
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 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.
private int hwdfrmTrackLog;
[DllImport("user32.dll")]
public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
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)
{
hwdfrmTrackLog = -1;
}
Registry
This code demonstrates how to read/write values in System Registry Key.
using Microsoft.Win32;
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.