views:

914

answers:

2

I have made a tiny application that responds to changes to files in a folder. But when I edit the file in Visual Studio 2008, it never detects anything. If I edit the file in Notepad instead, everything works as expected.

Surely Visual Studio saves the file at some point, but the watcher does not even trigger when I close the studio. Do you have any idea what I'm missing here?

This sample code (C#) should illustrate the problem:

FileSystemWatcher fileSystemWatcher = new FileSystemWatcher("C:\Test", "*.cs");
WaitForChangedResult changed = fileSystemWatcher.WaitForChanged(WatcherChangeTypes.All);
Console.Out.WriteLine(changed.Name);

I found a blog post by Ayende that describes the same problem, but unfortunately no solution.

+7  A: 

This was really mind boggling... when you try my example program below and change the file in VS, you will notice two lines in your output window:

Deleted

Renamed

So Visual Studio does never change an existing file, it saves the constents to a new file with a temporary name, then deletes the original file and renames the new file to the old name.

Actually, this is a good practice, because if you do it the usual way (just writing the changed file, which would cause the Changed event to be fired), the event handler may be called before the writing process is complete. If the event handler processes the file contents, this may cause problems because it would process an incomplete file.

In other words: It's not a bug, it's a feature ;-)

 static class Program
 {
  [STAThread]
  static void Main()
  {
   FileSystemWatcher FSW = new FileSystemWatcher("c:\\", "*.cs");

   FswHandler Handler = new FswHandler();

   FSW.Changed += Handler.OnEvent;
   FSW.Created += Handler.OnEvent;
   FSW.Deleted += Handler.OnEvent;
   FSW.Renamed += Handler.OnEvent;

   FSW.EnableRaisingEvents = true;

   System.Threading.Thread.Sleep(555000);
   // change the file manually to see which events are fired

   FSW.EnableRaisingEvents = false;
  }
 }
 public class FswHandler
 {
  public void OnEvent(Object source, FileSystemEventArgs Args)
  {
   Console.Out.WriteLine(Args.ChangeType.ToString());
  }
 }
}
Treb
That was not what I expected at all, but now it makes perfect sense. I suspect there is less chance of corrupting files in case of a crash, by doing it this way. Thank you!
Haugholt
+3  A: 

Just to document this possibility ...

From msdn:

If multiple FileSystemWatcher objects are watching the same UNC path in Windows XP prior to Service Pack 1, or Windows 2000 SP2 or earlier, then only one of the objects will raise an event. On machines running Windows XP SP1 and newer, Windows 2000 SP3 or newer or Windows Server 2003, all FileSystemWatcher objects will raise the appropriate events.

So my idea was that Visual Studio holds its own FileSystemWatcher on a file for whatever reason ... however you have no UNC paths and no mentioned OS.

tanascius
Good tip, thanks! The more I learn about the FileSystemWatcher, the less I like it...
Treb