Abstract:
If any one is experimenting your important directory without your notice, then you may think of an application, which helps you to monitor the changes of your directory. Earlier, writing this kind of application is too difficult, but with .NET you can do it through a simple and flexible component i.e. FileSystemWatcher, which watches your directory for any change using .NET. In this article, I am explaining you how to use FileSystemWatcher class in Part 1. In part 2, a sample application, which helps you to monitor a specified directory.
Introduction:
FileSystemWatcher is a very powerful component, which allows us to connect to the directories and watch for specific changes within them, such as creation of new files, addition of subdirectories and renaming of files or subdirectories. This makes it possible to easily detect when certain files or directories are created, modified or deleted. It is one of the members of System.IO namespace.
The FileSystemWatcher component is designed to watch for changes within the directory, not to changes to the directory's attributes themselves. For example, if you are watching a directory called c:\Mydir, the component will monitor changes within the directory but not changes to the directory itself.
The component can watch files on a local computer, network drive or a remote machine. FileSystemWatcher only works on Windows NT 4.0 and Windows 2000. You cannot watch a remote Windows NT 4.0 computer from a Windows NT 4.0 Computer. But, you can watch a remote Win2000 and local WinNT 4.0 and vice versa. Also you can watch a remote Win2000 and Win2000.
Requirements:
For the code in this article you will need:
Windows NT 4.0 or Windows 2000
NET Framework Beta 2
A text editor, such as Notepad, Text pad or Visual Studio .NET Beta2.
Configuring FileSystemWatcher Class:
To configure an instance of the FileSystemWatcher component,
- Create an instance of the FileSystemWatcher component.
- Configure necessary properties and methods for the component.
- Create Handlers for FileSystem Events.
Creating FileSystemWatcher Component Instances:
To create an instance of the FileSystemWatcher component use one of the following:
Example:
//Intializes a new instance of the FileSystemWatcher Class
//Intializes a new instance with a Path property
FileSystemWatcher myWatcher = new FileSystemWatcher("c:\\");
//Intializes a new instance along with a Path and Filter properties
FileSystemWatcher myWatcher = new FileSystemWatcher("c:\\","*.txt"); The component will not watch the specified directory until the Path is set, and EnableRaisingEvents is true. If you are using Visual Studio.NET, the FileSystemWatcher class is readily available in the Toolbox under the Components Tab and you can directly drag and drop the FileSystemWatcher class and EnableRaisingEvents is true by default.
Properties:
There are several properties you set for your FileSystemWatcher component instances to determine how they behave. These properties determine what directories and subdirectories the component instance will monitor and the exact occurrences within those directories that will raise events.
- Path - Sets or Gets the Path of the directory to watch.
- EnableRaisingEvents - Enable or disable the component.
- Filter - Gets or sets the filter string, used to determine what files are monitored in a directory. Default value is (*.*)
- IncludeSubdirectories - Enables or disables including subdirectories to be watched.
- InternalBufferSize - Gets or sets the size of internal buffer. Default is 8K.
- NotifyFilter - Gets or sets the type of changes to watch for.
Specifying Directories to Watch:
To specify what directories to be watched, Path and IncludeSubdirectories properties are used.
The Path property indicates the fully qualified path of the root directory you want to watch. This can be in standard directory notation(c:\directory) or in UNC format (\\server\directory).
Example:
FileSystemWatcher myWatcher = new FileSystemWatcher();
MyWatcher.Path = "c:\\";
The IncludeSubdirectories property indicates whether subdirectories within the root directory should be monitored. If the property is set to true, the component watches for the same changes in the subdirectories as it does in the main directory the component is watching.
Specifying the Changes to Watch:
Set Filter property to an empty string ("") to watch for changes in all files. To watch a specific file, set the Filter property to the file name say "samp.txt". You can also watch for changes in a certain type of file. For example, to watch for changes in document files, set the Filter property to "*.doc".
FileSystemWatcher class does not ignore hidden files. Setting the Filter does not decrease what goes into the buffer.
By setting NotifyFilter property to one of the NotifyFilters values, you can track several types of changes such as changes in Attributes, the LastWrite date and time, or the Size of files or directories or when security access to a file or directory rights changes. These values are all part of the NotifyFilters enumeration. You can set multiple changes to watch for by using "|" operator.
NotifyFilters enumeration:
| Name | Description |
| Attributes | The attributes of the file or folder. |
| CreationTime | The time the file or folder was created. |
| DirectoryName | The name of the directory. |
| FileName | The name of the file. |
| LastAccess | The date the file or folder was last opened. |
| LastWrite | The date the file or folder last had anything written to it. |
| Security | The security settings of the file or folder. |
| Size | The size of the file or folder. |
Example:
FileSystemWatcher myWatcher = new FileSystemWatcher();
myWatcher.Path = "c:\\";
myWatcher.Filter = "*.txt";
myWatcher.EnableRaisingEvents = true;
myWatcher.IncludeSubdirectories = false;
myWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
To avoid a buffer overflow, use the NotifyFilter and IncludeSubdirectories properties so you can filter out unwanted change notifications.
Methods:
In addition to using the FileSystemWatcher component to immediately monitor a specific directory, you can use the WaitForChanged method to wait until a specific event occurs and then continue with execution of the thread. For example, if you are working with a Web-based news application, you might create an admin portion of the site where users upload their news stories. You could use the WaitForChanged method to watch that directory until the last access date changes, and then begin processing the news directory for new articles.
You specify the type of change to watch for by setting the value of a WatcherChangeType enumeration. The possible values are as follows:
| Member Name | Description |
| All | The creation, deletion, change, or renaming of a file or folder. |
| Changed | The change of a file or folder. The types of changes include: changes to size, attributes, security settings, last write, and last access time. |
| Created | The creation of a file or folder. |
| Deleted | The deletion of a file or folder. |
| Renamed | The renaming of a file or folder. |
WaitForChanged is a synchronous method that returns an object of type WaitForChangedResult. This class contain specific information on the type of change that occurred in the directory. You can access information such as Name, OldName, and TimedOut on this object to find out more about the change. TimeOut is the time (in milliseconds) to wait before timing out.
If you use it in a Windows Form application, the application would stop responding if the method was used on the UI thread instead of the worker thread.
The following code track for all the changes.
Example:
1)myWatcher.WaitForChanged(WatcherChangeType.All);
2)myWatcher.WaitForChanged(WatcherChangeType.All,1000); Creating Handler for FileSystem Events:
The FileSystemWatcher Component raises four events depending on the types of changes that occur in the directory it is watching. These events are
- Created - raised whenever a directory or file is created.
- Deleted - raised whenever a directory or file is deleted.
- Renamed - raised whenever the name of a directory or file is changed.
- Changed - raised whenever changes are made to the size, system attributes, last write time, last access time or NTFS security permissions of a directory or file.
To access these events, you have to define handlers that automatically call methods in your code when a change occurs. To create a handler, use the following code:
Example:
//Handler for Changed Event
myWatcher.Changed += new FileSystemHandler(myWatcher_Changed);
//Handler for Created Event
myWatcher.Created += new FileSystemHandler(myWatcher_Created);
//Handler for Deleted Event
myWatcher.Deleted += new FileSystemHandler(myWatcher_Deleted);
//Handler for Renamed Event
myWatcher.Renamed += new RenamedEventHandler(myWatcher_Renamed);
Although some common occurances, such as copying or moving a file, do not correspond directly to an event, these occurances do cause events to be raised. When you copy a file, the system raises a Created event in the directory to which the file was copied but does not raise any events in the original directory. When you move a file, the server raises two events: a Deleted event in the source directory, followed by a Created event in the target directory.
For example, you create two instances of FileSystemWatcher. FileSystemWatcher1 is set to watch "C:\My Documents", and FileSystemWatcher2 is set to watch "C:\Your Documents". Now, if you copy a file from "My Documents" into "Your Documents", a Created event will be raised by FileSystemWatcher2, but no event is raised for FileSystemWatcher1. Unlike copying, moving a file or directory would raise two events. From the previous example, if you moved a file from "My Documents" to "Your Documents", a Created event would be raised by FileSystemWatcher2 and a Deleted event would be raised by FileSystemWatcher1.
Happy .NET Programming!!
bala saravananPosted Mar 17, 2012, 2:46 AM
so nice
MK DASPosted Dec 17, 2011, 9:55 AM
I am not able to access the path/folder in a remote server in LAN. I am using \\IP Address\\Drive Name\\folder name\\
ariezPosted Jun 24, 2010, 7:31 AM
I want to monitor the activities of all the folders present at "C:\Inetpub\ftproot\san".User can work on any type of files and not only text files.Since we have given 1GB space (lets say) to each user, so user can do anything to utilize this space. Variable "id" is redirected to this page from previous page and according to this id the respective folder of user is opened in windows explorer. Now I want to monitor the activites that the user will do in his folder like creating new file, deleting an existing file or editing a file.I want to monitor user's activities because i have to keep track of the space given to the user so tht i can restrict the user to use 1GB space only and not more than that. Question: How and where to observe the functionality of this code.I m using ASP.NET and its a web based application. Many Thanks using System.IO; using System.Threading; using System.Diagnostics; public partial class _Default : System.Web.UI.Page { DAL conn; string connection; string id = string.Empty; protected void Page_Load(object sender, EventArgs e) { connection = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Documents and Settings\\project\\Desktop\\BE prj\\dbsan.mdb;Persist Security Info=False"; conn = new DAL(connection); ////*** Opening Respective Folder of a User ***//// DirectoryInfo directories = new DirectoryInfo(@"C:\\Inetpub\\ftproot\\san\\"); //DirectoryInfo directories = new DirectoryInfo(@"C:\"); DirectoryInfo[] folderList = directories.GetDirectories(); if (Request.QueryString["id"] != null) id = Request.QueryString["id"]; string path = Path.Combine(@"C:\\Inetpub\\ftproot\\san\\", id); int folder_count = folderList.Length; for (int j = 0; j < folder_count; j++) if (Convert.ToString(folderList[j]) == id) { Process p = new Process(); p.StartInfo.FileName = path; p.Start(); } ClsFileSystemWatcher FSysWatcher = new ClsFileSystemWatcher(); FSysWatcher.FileWatcher(path); } public class ClsFileSystemWatcher { public void FileWatcher(string InputDir) { using (FileSystemWatcher fsw = new FileSystemWatcher()) { fsw.Path = InputDir; fsw.Filter = @"*"; fsw.IncludeSubdirectories = true; fsw.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Attributes | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size | NotifyFilters.CreationTime | NotifyFilters.DirectoryName; fsw.Changed += new FileSystemEventHandler(OnChanged); fsw.Created += new FileSystemEventHandler(OnCreated); fsw.Deleted += new FileSystemEventHandler(OnDeleted); fsw.Renamed += new RenamedEventHandler(OnRenamed); fsw.Error += new ErrorEventHandler(OnError); fsw.EnableRaisingEvents = true; //string strOldFile = InputDir + "OldFile.txt"; //string strNewFile = InputDir + "CreatedFile.txt"; //// Making changes in existing file //using (FileStream stream = File.Open(strOldFile, FileMode.Append)) //{ // StreamWriter sw = new StreamWriter(stream); // sw.Write("Appending new line in Old File"); // sw.Flush(); // sw.Close(); //} //// Writing new file on FileSystem //using (FileStream stream = File.Create(strNewFile)) //{ // StreamWriter sw = new StreamWriter(stream); // sw.Write("Writing First line into the File"); // sw.Flush(); // sw.Close(); //} //File.Delete(strOldFile); //File.Delete(strNewFile); // Minimum time given to event handler to track new events raised by the filesystem. Thread.Sleep(1000); } } public static void OnChanged(object source, FileSystemEventArgs e) { Console.WriteLine("File " + e.FullPath + " :" + e.ChangeType); } public static void OnDeleted(object source, FileSystemEventArgs e) { Console.WriteLine("File " + e.FullPath + " :" + e.ChangeType); } public static void OnCreated(object source, FileSystemEventArgs e) { Console.WriteLine("File " + e.FullPath + " :" + e.ChangeType); } public static void OnRenamed(object source, RenamedEventArgs e) { Console.WriteLine("File " + e.OldFullPath + " [Changed to] " + e.FullPath); } public static void OnError(object source, ErrorEventArgs e) { Console.WriteLine("Error " + e.ToString()); } } }
roger harrisPosted Apr 14, 2009, 2:44 PM
Hi, I'm not a programmer :-( I'm using Visual Basic 2008 What I'm trying to do is get the name of the file which triggers the FileSystemWatcher event. In other words, I change the contents of an existing file in the directory being monitored by the watcher. When the watcher picks up the change, I want to parse the contents of the changed file into a new file, re-formatting the layout as i go. I can do the last bit, no problem. But how do I get the name of the file which was changed/saved in the first place? I am thinking it must be something to do with the properties of the FileSystemWatcher. However, )any_ of the files in the 'watched' directory could be changed. eg: 1) I change the contenst of the file new.txt and sa ve the changes. 2) Once changed I want the conents of the file new.txt written to the file latest.txt 3) Now I change the contents of the file old.txt and save again. 4) This time I want the contents of the file old.txt to be written to the file latest.txt so i have to get the name of the file which has been changed from the FileSystemWatcher - er, how? Many thanks
Paul PacurarPosted Feb 13, 2008, 8:29 AM
Hello all, I'm using FileSystemWatcher from OpenNETCF.IO. (CF 1.0) and it works, but when my app exits I get NullReferenceException. Does anyone know what's the problem? (I don't need events for everything, just for creation and deletion, so I don't assign an event handler for the others...) Thank You in advance
Paul RossPosted Nov 11, 2007, 9:43 PM
Hi there For some reason, my Changed Event is firing twice when I change a file in the monitored folder. Here is my code: private void SetupFileSystemWatcher ( out FileSystemWatcher fileSystemWatcher, String dataFileFolderPath ) { fileSystemWatcher = new FileSystemWatcher ( dataFileFolderPath ); fileSystemWatcher.Filter = "*.xml"; fileSystemWatcher.IncludeSubdirectories = false; fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Changed += new FileSystemEventHandler ( fileSystemWatcher_Changed ); fileSystemWatcher.EnableRaisingEvents = true; } private void fileSystemWatcher_Changed ( object sender, FileSystemEventArgs e ) { Console.WriteLine ( "File Changed" ); } Process Monitor is definitely only showing only one change to the file... what am I missing? Thanks in advance Paul
Hanym hanym halimPosted Aug 21, 2007, 11:27 PM
I've successfully run my script(VB) on moving and renaming files. but now i wanna move the files based on the file's latest modified date, but i donno how?