Почему FileSystemWatcher не обнаруживает изменения в Visual Studio?

Я сделал небольшое приложение, которое реагирует на изменения файлов в папке. Но когда я редактирую файл в Visual Studio 2008, он никогда ничего не обнаруживает. Если я отредактирую файл в "Блокноте", все будет работать так, как ожидалось.

Конечно, Visual Studio сохраняет файл в какой-то момент, но наблюдатель даже не запускается, когда я закрываю студию. Вы знаете, что мне здесь не хватает?

Этот пример кода (С#) должен показать проблему:

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

Я нашел сообщение в блоге от Ayende, в котором описывается одна и та же проблема, но, к сожалению, нет решения.

Ответ 1

Это было действительно ошеломляюще... когда вы попробуете мою примерную программу ниже и измените файл в VS, вы заметите две строки в окне вывода:

Удалено

Переименован

Итак, Visual Studio никогда не меняет существующий файл, он сохраняет константы в новый файл с временным именем, затем удаляет исходный файл и переименовывает новый файл в старое имя.

Собственно, это хорошая практика, потому что, если вы делаете это обычным способом (просто записывая измененный файл, что приведет к запуску события Changed), обработчик события может быть вызван до того, как процесс записи будет полный. Если обработчик событий обрабатывает содержимое файла, это может вызвать проблемы, поскольку он обрабатывает неполный файл.

Другими словами: это не ошибка, это особенность; -)

    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());
        }
    }
}

Ответ 2

Просто для документирования этой возможности...

От msdn:

Если несколько объектов FileSystemWatcher просматривают один и тот же UNC-путь в Windows XP до пакета обновления 1 (SP1) или Windows 2000 с пакетом обновления 2 (SP2) или более ранних версий, то только один из объектов вызывает событие. На компьютерах под управлением Windows XP с пакетом обновления 1 (SP1) и более поздних версиях, Windows 2000 SP3 или более поздней версии или Windows Server 2003 все объекты FileSystemWatcher поднимут соответствующие события.

Итак, моя идея заключалась в том, что Visual Studio имеет собственный файл FileSystemWatcher по какой-либо причине... однако у вас нет UNC-путей и не упомянутой ОС.

Ответ 3

Решено, указав свойство NotifyFilter:

FileSystemWatcher w = new FileSystemWatcher();           
w.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite 
| NotifyFilters.CreationTime;