Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FileSystemWatcher does not raise events for files that are opened/changed in Visual Studio #17626

Closed
robinsedlaczek opened this issue Jun 16, 2016 · 4 comments
Milestone

Comments

@robinsedlaczek
Copy link

Summary

FileSystemWatcher does not raise events for files that are opened/changed in Visual Studio. It works as expected when using another editor like notepad.

Context

Visual Studio 2015
Visual Studio 15 Preview 2
.NET 4.6.1

Steps to reproduce

  1. Create a FileSystemWatcher that watches files (in common application data folder) like this:

    var configFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "ForceFeedbackProgramming");
    
    if (!Directory.Exists(configFolderPath))
       Directory.CreateDirectory(configFolderPath);
    
    var watcher = new FileSystemWatcher()
    {
       Path = configFolderPath,
       NotifyFilter = NotifyFilters.LastWrite,
       Filter = "Config.json"
    };
    
    watcher.Changed += OnFileChanged;
    watcher.EnableRaisingEvents = true;
    
    return watcher;
    
  2. Create a file named "Config.json" in the watched folder (in this example: "CommonApplicationData\ForceFeedbackProgramming").

  3. Run the code from above and set a breakpoint in the OnFileChanged event handler.

  4. Open the Config.json file in Visual Studio, edit it and save it.

Current Behavior

The event handler is not called and you'll never hit the breakpoint. So I guess, the event is not raised. When checking the Config.json file, the file changed date was set correctly. When viewing the file in another text editor, all changes that have been made in Visual Studio are there. So the file was saved correctly by Visual Studio. So I would assume that the FileSystemWatcher would raise the appropriate events. But it does not. Editing the file in another editor like notepad causes the FileSystemWatcher to raise the events. So the code above works as expected.

Expected Behavior

I would expect that events are raised by the FileSystemWatcher when the watched file(s) are changed and saved in Visual Studio.

@stephentoub
Copy link
Member

This isn't a bug in FileSystemWatcher... Visual Studio just isn't doing what you think it's doing. Try changing your code to instead look like:

using System;
using System.IO;

class Program
{
    static void Main()
    {
        var configFolderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "ForceFeedbackProgramming");

        if (!Directory.Exists(configFolderPath))
            Directory.CreateDirectory(configFolderPath);

        var watcher = new FileSystemWatcher()
        {
            Path = configFolderPath,
            NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName,
        };

        watcher.Created += (s, e) => Console.WriteLine("Created: " + e.FullPath);
        watcher.Deleted += (s, e) => Console.WriteLine("Deleted: " + e.FullPath);
        watcher.Changed += (s, e) => Console.WriteLine("Changed: " + e.FullPath);
        watcher.Renamed += (s, e) => Console.WriteLine("Renamed: " + e.OldFullPath + " to " + e.FullPath);
        watcher.EnableRaisingEvents = true;

        Console.ReadLine();
    }
}

then edit/save the file in Visual Studio... you should see events something like:

Created: ForceFeedbackProgramming\5jny54l2.szi~
Changed: ForceFeedbackProgramming\5jny54l2.szi~
Created: ForceFeedbackProgramming\Config.json~RF2249be8.TMP
Deleted: ForceFeedbackProgramming\Config.json
Changed: ForceFeedbackProgramming\Config.json~RF2249be8.TMP
Renamed: ForceFeedbackProgramming\5jny54l2.szi~ to ForceFeedbackProgramming\Config.json
Deleted: ForceFeedbackProgramming\Config.json~RF2249be8.TMP

In other words, Visual Studio is writing to temporary files, deleting the original file, and then moving the temporary to be the new one.

@robinsedlaczek
Copy link
Author

Many thanks for the explanation. My filter for a specific file made me blind for the changes in the directory.

But I don't know if I like this. We also use temporaries when loading, editing and saving files. But that is under the hood and completely transparent for the user. So maybe other developers get confused like me, too. So wouldn't it be an option, that the FileSystemWatcher raises the Changed event when a file was created and the NotifyFilter has the LastWrite flag set? So we can see the Created event first, followed by the Changed event? From a semantic point of view, it wouldn't be incorrect: file creation means, that there was a write operation, too. The example from above would work.

@stephentoub
Copy link
Member

But that is under the hood and completely transparent for the user

So is FileSystemWatcher: it's a low-level eventing system that simply passes along the events from the OS. The OS is reporting these events, and, in my opinion, applying a heuristic on top that tries to reinterpret them based on a particular series of events would arguably be misleading for various scenarios. I do understand what you're looking for, but if you want such a heuristic, you can layer that on top of the lower-level events supplied by FSW, and you can do so with basically the same fidelity that we would be able to in the FSW implementation itself.

@robinsedlaczek
Copy link
Author

I can live with that in my particular case. I argue from the FSW API point of view and if the API is natural/intuitive enough here. Well, I think that a file creation is a write operation as well, and so I would expect a Changed event, too - that is no heuristic, that is a question of definition. But as you said, if it should simply pass along the OS events, a different behavior or heuristic could be dangerous in a lot of scenarios. Maybe the documentation could be more clear here. :-)

Many thanks for your explanations!

@msftgits msftgits transferred this issue from dotnet/corefx Jan 31, 2020
@msftgits msftgits added this to the 1.1.0 milestone Jan 31, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants