?
Solved

Help with the FileSystemWatcher Object in .NET

Posted on 2009-04-19
8
Medium Priority
?
710 Views
Last Modified: 2013-12-17
Hi Experts,

I am getting some odd behaviour with the FileSystemWatcher object. Please refer to my code snippets below:
Whenever I create a new XML file in the specified directory the file name get printed twice as opposed to a single time. Tried setting a breakpoint in my eventhandler and it looks like the function is getting called twice which doesnt explain things.

 What I am trying to achieve is to read the contents of the newly created and then delete it. So if the function get called twice,it will through up a filenotfound exception the second time. Came across this oddy while testing. What am I missing in here.

static void Main(string[] args)
        {
 
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"C:\XmlFiles";
            watcher.Filter = "*.xml";
            watcher.Created += new FileSystemEventHandler(FileCreated);
            watcher.EnableRaisingEvents = true;
            Console.WriteLine("Started...");
            Console.ReadLine();
        }
 
        static void FileCreated(object sender, FileSystemEventArgs e)
        {
           Console.WriteLine(e.FullPath);
         }

Open in new window

0
Comment
Question by:Axonites
  • 4
  • 2
  • 2
8 Comments
 
LVL 39

Expert Comment

by:abel
ID: 24181106
Interesting. I just copied your code into a winforms application and I can't replicate your behavior. How are you trying to create the file? Can you try to select the file in an Explorer window an hit Ctrl-C / Ctrl-V and check if that also creates two events?

What version of .NET are you on?
0
 
LVL 11

Accepted Solution

by:
anyoneis earned 1000 total points
ID: 24181581
I have gathered from google that this matter of duplicate events is due to antivirus software. But, it's our job to get around it. There are several scenarios that you have to deal with - and various programs will handle each scenario differently. For example, one program might delete an existing file then recreate it. Another might truncate it and write it....

Here is what I do, it seems to work well:
When a file changes, I start a timer for that file. I keep track of the file and the timer in a hash table.

When the timer expires, I lock the hash table and find the timer. Then, I try to open the file. If I get it, I assume that the changes to the file are done and I process the file. Otherwise I reset the timer for another time period (I use 5 seconds - way more than I probably need to.)

This seems to reliably capture files that are dropped in, and files that are created and expanded within my watched directory.

There are a bunch of details. For example, it is possible that you would get a create, then a tijmer expiration, then another create before the file available status happens. Your time window must be small enough to make this eventuality unlikely, if you must capture each instance of the changed file.

David
0
 

Author Comment

by:Axonites
ID: 24181587
Hi Abel,

I am running dotnet 3.5, got my xml file opened in an editor. when I save it onto C:\XmlFiles using different file names the created event triggers and calls the FileCreated method which is my event handler for the same.

Now Interestingly when I try the Ctrl-C/Ctrl-V sequence the event handler gets called only once.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 11

Expert Comment

by:anyoneis
ID: 24181588
Oh, to answer your present question, in the first create event, you will find that FileInfo(e.FullPathName).Exists is false. But it is true on the second call.

David
0
 
LVL 11

Expert Comment

by:anyoneis
ID: 24181622
Here is a console program based on yours that will help illustrate the issues.

If I re-save a pre-exsting file XMLFile2.xml then create a new one XMLFile4.xml, I get:

Started...
File Changed Event
        C:\XmlFiles\XMLFile2.xml
        Exists and is 56 bytes
File Changed Event
        C:\XmlFiles\XMLFile2.xml
        Exists and is 56 bytes
File Created Event
        C:\XmlFiles\XMLFile4.xml
        Does not exist
File Deleted Event
        C:\XmlFiles\XMLFile4.xml
        Does not exist
File Created Event
        C:\XmlFiles\XMLFile4.xml
        Exists and is 56 bytes
File Changed Event
        C:\XmlFiles\XMLFile4.xml
        Exists and is 56 bytes
File Changed Event
        C:\XmlFiles\XMLFile4.xml
        Exists and is 56 bytes




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
namespace FileSystemWatcherTest
{
    class Program
    {
        
        static void Main(string[] args)
        {
            FileSystemWatcher watcher = new FileSystemWatcher();
            watcher.Path = @"C:\XmlFiles";
            watcher.Filter = "*.xml";
            watcher.Created += new FileSystemEventHandler(FileCreated);
            watcher.Deleted += new FileSystemEventHandler(FileDeleted);
            watcher.Changed += new FileSystemEventHandler(FileChanged);
            watcher.Renamed += new RenamedEventHandler(FileRenamed);
            watcher.EnableRaisingEvents = true;
            Console.WriteLine("Started...");
            Console.ReadLine();
        }
 
        static void DisplayStuff(object sender, FileSystemEventArgs e)
        {
            Console.WriteLine("File {0} Event", e.ChangeType);
            Console.WriteLine("\t{0}", e.FullPath);
 
            FileInfo fInfo = new FileInfo(e.FullPath);
            if (fInfo.Exists)
                Console.WriteLine("\tExists and is {0} bytes", fInfo.Length);
            else
                Console.WriteLine("\tDoes not exist");
        }
 
        static void DisplayRenameStuff(object sender, RenamedEventArgs e)
        {
            Console.WriteLine("File {0} Event", e.ChangeType);
            Console.WriteLine("\tNew Name: {0}", e.FullPath);
            Console.WriteLine("\tOld Name: {0}", e.OldFullPath);
 
            FileInfo fInfo = new FileInfo(e.FullPath);
            if (fInfo.Exists)
                Console.WriteLine("\tExists and is {0} bytes", fInfo.Length);
            else
                Console.WriteLine("\tDoes not exist");
        }
 
        static void FileCreated(object sender, FileSystemEventArgs e)
        {
            DisplayStuff(sender, e);
        }
 
        static void FileDeleted(object sender, FileSystemEventArgs e)
        {
            DisplayStuff(sender, e);
        }
        static void FileChanged(object sender, FileSystemEventArgs e)
        {
            DisplayStuff(sender, e);
        }
        static void FileRenamed(object sender, RenamedEventArgs e)
        {
            DisplayRenameStuff(sender, e);
        }
    }
}

Open in new window

0
 

Author Comment

by:Axonites
ID: 24181715
Hi anyoneis,

Really appreciate your time in providing a detailed example.
Can you explain to me whats happening in one of your test cases as below:

File Created Event
        C:\XmlFiles\XMLFile4.xml
        Does not exist

I came across a similar situation, when I tried to open the file created, from  my create event handler a file not found exception was thrown.
Any reason for this behavior?
0
 
LVL 39

Assisted Solution

by:abel
abel earned 1000 total points
ID: 24181776
> Now Interestingly when I try the Ctrl-C/Ctrl-V sequence the event handler gets called only once.

that looks promising. Probably (not sure) the first time the XML file is "touched", which is to make sure it can be created (similar to hitting rightmouseclick in Explorer and then "New Text File", first a file is created, then the rename). It might very well be that the first Created event would be about a file not containing anything. As anyoneis has said, this might also be due to the presence of a virus scanner.

Now, if you do need to react to these double events as created by this program, and you need to act on them, I would wait a while for the second event to happen. If it doesn't happen, you process and remove the file. If it does happen, you do the same.

What I mean with "wait for the same event to happen" you can do as follows (needs some tweaking, but you'll get my drift):

private void FileCreated(object sender, FileSystemEventArgs e)
{
    watcher.EnableRaisingEvents = false;
    WaitForChangedResult result;
    result = watcher.WaitForChanged(WatcherChangeTypes.Created, 1000);
    if (!result.TimedOut)
        Console.WriteLine(e.FullPath + " has been twice created");
    else
        Console.WriteLine(e.FullPath + " has been created");
 
    watcher.EnableRaisingEvents = true;
}

Open in new window

0
 
LVL 11

Expert Comment

by:anyoneis
ID: 24182191
I don't know what the reason is for the non-existent file on the created event, but I do know that it gives you a way to distinguish between the two events.

David
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Wouldn’t it be nice if you could test whether an element is contained in an array by using a Contains method just like the one available on List objects? Wouldn’t it be good if you could write code like this? (CODE) In .NET 3.5, this is possible…
A long time ago (May 2011), I have written an article showing you how to create a DLL using Visual Studio 2005 to be hosted in SQL Server 2005. That was valid at that time and it is still valid if you are still using these versions. You can still re…
Screencast - Getting to Know the Pipeline
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses
Course of the Month17 days, 7 hours left to enroll

831 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question