A user a devpinoy.org posted a question on the forum section asking if there's a way to restrict files from being saved in a directory. I know you can do this via the FileSystemWatcher class so I quickly whipped my Visual Studio 2008 IDE and started building a prototype application to demonstrate the solution.
The first thing that you need to do is to set-up some key details on what we want to watch/monitor
private const string ALLOWED_FILE_EXTENSION = ".doc";
private const string DEFAULT_WATCH_FOLDER = @"E:\Test Folder\";
Next, the FileSystemWatcher specify what directory you want to monitor.
FileSystemWatcher watcher = new FileSystemWatcher(DEFAULT_WATCH_FOLDER);
After that you need to setup the notification filters on what type of filesystem changes you want to watch;
watcher.NotifyFilter = NotifyFilters.LastAccess |
NotifyFilters.LastWrite |
NotifyFilters.FileName |
NotifyFilters.DirectoryName |
NotifyFilters.CreationTime;
And finally, we need to set-up the FileSystem events you want our FileSystem. In this case, we only want to monitor Created and Renamed events.
watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
Now, let's start coding our event handlers.
For our event handler, I decided to use one method that would handle both the Created and Rename event. Ideally you want to seperate this to into two different methods because you might want to handle the tow events differently but since all I want to do is to block files\folders that doesn't match my criteria i decided to handle them both using a single method called FileSystemHandler.
void watcher_Renamed(object sender, RenamedEventArgs e)
{
FileSystemHandler(e.Name, e.FullPath);
}
void watcher_Created(object sender, FileSystemEventArgs e)
{
FileSystemHandler(e.Name, e.FullPath);
}
Below is the implementation detail for our FileSystemHandler method.
void FileSystemHandler(string name, string fullpath)
{
try
{
//read the contents of our directory
DirectoryInfo di = new DirectoryInfo(DEFAULT_WATCH_FOLDER);
//get the filesysteminfo[] objects
FileSystemInfo[] fileSystemInfoArray = di.GetFileSystemInfos();
//there's always going to be one object matching this criteria all the time
FileSystemInfo found = fileSystemInfoArray.Single(f => f.FullName.Equals(fullpath));
//if it finds something
if (found != null)
{
//cast the found object to directoryinfo
DirectoryInfo d = found as DirectoryInfo;
//if it's null it means it's a FileInfo object
if (d == null)
{
//cast found to a fileinfo object
FileInfo f = found as FileInfo;
//delete the file if the extension doesn't match our desired/allowed extension
if (!f.Extension.Equals(ALLOWED_FILE_EXTENSION))
{
f.Delete();
}
}
else
{
//directories are not allowed on this folder too!
d.Delete(true);
}
}
}
catch
{
//let it sleep for 30 seconds
Thread.Sleep(30000);
//it failed so we need to try again recussively
/*
note: it's a good idea to set a retry limit here because if we don't
then the app will retry to infinity but i'll leave that up to you.
*/
FileSystemHandler(name, fullpath);
}
}
What the function above is doing is that it checks to see if the filesystem object that was created on the directory is either a file or a directory. If it is a directory, automatically delete it since we dont want any directory to be saved on our folder. If it is a file we need to check if it's extension matches the allowed file extension. If it matches the allowed extension we let it thru. If it doesn't we call the the Delete method on the FileInfo object to delete the file.
All we need to do now is to tell the watcher to start monitor our folder
watcher.EnableRaisingEvents = true;
Setting EnableRaisingEvents to true triggers our watcher to start monitoring the folder. Setting it to false will stop the watcher.
And we are done! Now we have an application that blocks saving or renaming of files in a folder that doesn't match the allowed file extension.
Below is the full listing of the code for the demo project I built for this article:
using System;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Threading;
namespace KeithRull.FolderSpy
{
public partial class MainForm : Form
{
private bool IsCurrentlyWatching = false;
private const string ALLOWED_FILE_EXTENSION = ".doc";
private const string DEFAULT_WATCH_FOLDER = @"E:\Test Folder\";
FileSystemWatcher watcher;
public MainForm()
{
InitializeComponent();
}
private void MainForm_Load(object sender, EventArgs e)
{
SetUpWatcher();
}
private void watchButton_Click(object sender, EventArgs e)
{
if (!IsCurrentlyWatching)
{
watchButton.Text = "Stop watching";
IsCurrentlyWatching = true;
//start the watcher
watcher.EnableRaisingEvents = true;
}
else
{
watchButton.Text = "Start watching";
IsCurrentlyWatching = false;
//stop the watcher
watcher.EnableRaisingEvents = false;
}
}
void watcher_Renamed(object sender, RenamedEventArgs e)
{
FileSystemHandler(e.Name, e.FullPath);
}
void watcher_Created(object sender, FileSystemEventArgs e)
{
FileSystemHandler(e.Name, e.FullPath);
}
void FileSystemHandler(string name, string fullpath)
{
try
{
//read the contents of our directory
DirectoryInfo di = new DirectoryInfo(DEFAULT_WATCH_FOLDER);
//get the filesysteminfo[] objects
FileSystemInfo[] fileSystemInfoArray = di.GetFileSystemInfos();
//there's always going to be one object matching this criteria all the time
FileSystemInfo found = fileSystemInfoArray.Single(f => f.FullName.Equals(fullpath));
//if it finds something
if (found != null)
{
//cast the found object to directoryinfo
DirectoryInfo d = found as DirectoryInfo;
//if it's null it means it's a FileInfo object
if (d == null)
{
//cast found to a fileinfo object
FileInfo f = found as FileInfo;
//delete the file if the extension doesn't match our desired/allowed extension
if (!f.Extension.Equals(ALLOWED_FILE_EXTENSION))
{
f.Delete();
}
}
else
{
//directories are not allowed on this folder too!
d.Delete(true);
}
}
}
catch
{
//let it sleep for 30 seconds
Thread.Sleep(30000);
//it failed so we need to try again recussively
/*
note: it's a good idea to set a retry limit here because if we don't
then the app will retry to infinity but i'll leave that up to you.
*/
FileSystemHandler(name, fullpath);
}
}
void SetUpWatcher()
{
watcher = new FileSystemWatcher(DEFAULT_WATCH_FOLDER);
watcher.NotifyFilter = NotifyFilters.LastAccess |
NotifyFilters.LastWrite |
NotifyFilters.FileName |
NotifyFilters.DirectoryName |
NotifyFilters.CreationTime;
watcher.Created += new FileSystemEventHandler(watcher_Created);
watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
}
}
}
As always, you can download the code for the complete project here: KeithRull.FolderSpy.zip (40.38 KB)