Hi I am creating a windows service to watch certain directories to see if the size of the directory is reaching its limit. I have created a file system watcher as follows:
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = dirPaths[i].ToString();
watcher.NotifyFilter = NotifyFilters.Size;
watcher.EnableRaisingEvents = true;
watcher.Changed += new FileSystemEventHandler(OnChanged);
and
private void OnChanged(object source, FileSystemEventArgs e)
{
try
{
string directory = new DirectoryInfo(e.FullPath).Parent.FullName;//gettting the directory path from the full path
float dirSize = CalculateFolderSize(directory);
float limitSize = int.Parse(_config.TargetSize);//getting the limit size
if (dirSize > limitSize)
{
eventLogCheck.WriteEntry("the following path has crossed the limit " + directory);
//TODO: mail sending
}
}
catch (Exception ex)
{
eventLogCheck.WriteEntry(ex.ToString());
}
}
CalculateFolderSize
checks the size of all the files and subdirectories in the drive.
Now this works fine when I add a file to the directory e.g. a .xls, .txt, etc. file but if I add a folder to the directory it does not trigger the OnChanged
event??
if I enable:
watcher.IncludeSubdirectories = true;
it does trigger the Onchanged
event but in this case it only checks the subdirectory and not the entire directory.
Please can someone tell me how I can get this to work such that when I copy a folder to the directory being watched it triggers the Onchanged
event and calculates the new size of the directory.
my CalculateFolderSize
function is as follows if this helps:
//function to calculate the size of the given path
private float CalculateFolderSize(string folder)
{
float folderSize = 0.0f;
try
{
//Checks if the path is valid or not
if (!Directory.Exists(folder))
{
return folderSize;
}
else
{
try
{
foreach (string file in Directory.GetFiles(folder))
{
if (File.Exists(file))
{
FileInfo finfo = new FileInfo(file);
folderSize += finfo.Length;
}
}
foreach (string dir in Directory.GetDirectories(folder))
{
folderSize += CalculateFolderSize(dir);
}
}
catch (NotSupportedException ex)
{
eventLogCheck.WriteEntry(ex.ToString());
}
}
}
catch (UnauthorizedAccessException ex)
{
eventLogCheck.WriteEntry(ex.ToString());
}
return folderSize;
}
You're using the folder path provided by the FileSystemEventArgs
so that will be the folder that has changed. Instead, create an object for each directory root that you are monitoring and, inside it, store the root path and use that instead of the EventArgs
.
You may find an easy way to create this object is just to use a lambda function for the event handler as follows. This effectively wraps up the path from the outer scope into a different object for each path you are monitoring.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = dirPaths[i].ToString();
watcher.NotifyFilter = NotifyFilters.Size;
watcher.EnableRaisingEvents = true;
watcher.Changed += delegate (object source, FileSystemEventArgs e)
{
float dirSize = CalculateFolderSize(watcher.Path); // using the path from the outer scope
float limitSize = int.Parse(_config.TargetSize);//getting the limit size
if (dirSize > limitSize)
{
eventLogCheck.WriteEntry("the folloing path has crossed the limit " + directory);
//TODO: mail sending
}
};