1

I have a pet project I'm working on where the FileSystemWatcher is vexing me.

Here's the initialization code:

for (var xx = 0; xx < _roots.Count; xx++)
{
    var watcher = new FileSystemWatcher();
    var root = _roots[xx];

    watcher.Path = root;
    // watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;

    watcher.Filter = "*.*";
    watcher.Changed += new FileSystemEventHandler(OnChanged);
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);

    watcher.EnableRaisingEvents = true;

    _rootWatchers.Add(watcher);
}

Let's say the root we're watching "c:\root" and there's a sub directory "c:\root\subdir" that contains a file called "file1.txt".

The watcher is up and running and I delete "file1.txt". When the handler is called and examine the values of FileSystemEventArgs.

I expect for e.Name == "file1.txt" and e.FullPath == "c:\\root\\subdir\\file1.txt.

The actual values are "subdir" and "c:\\root\\subdir".

I'm sure it's something simple I missed in the documentation somewhere.

3
  • I think this might help: stackoverflow.com/questions/11255360/… Commented Jan 11, 2018 at 18:53
  • That was one of the first questions I read on the FileSystemWatcher before asking my question. It doesn't help as it covers using the instance properties of Name and FullName to get the information. This question is about the event returning the directory information rather than the file information. Commented Jan 11, 2018 at 19:09
  • Just an idea I would try if I was near a keyboard right now: set up a test with just the deletion monitoring for one path. If the file details are as expected, add in the rest of your complexity to see if anything else on the code sample is causing an issue. Every article I’ve seen about file watcher indicates the file path should be reported (as a relative path I think). Maybe you mapping several event handlers to the same method is muddying your water. Just a guess. I’d run some tests but I’m on my phone atm Commented Jan 11, 2018 at 19:14

1 Answer 1

4

You are correct, the issue you are facing is practically one of forgetting to set a property.

If you set watcher.IncludeSubdirectories = true;, you'll get notified about the file deletion even in deeper levels.

In the default mode, the FileSystemWatcher only records changes to the given directory. Sub-directories being modeled sort of directory entries similar to files, any additions/deletions inside them are just reported as changes directly to the sub-directories (you would see that if you checked the FileSystemEventArgs.ChangeType property in the OnChanged handler).

Even if you turn on sub-directories monitoring, you'll still get a change event (FileSystemEventArgs.ChangeType = WatcherChangeTypes.Changed) for the subdir directory as it is also modified when you delete a file inside it. That is in addition to the deletion event for the file.

My test code:

static void Main(string[] args)
{
    var watcher = new FileSystemWatcher();

    watcher.Path = @"C:\test_dir";
    // watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
    watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;

    watcher.Filter = "*.*";
    watcher.Changed += new FileSystemEventHandler(OnChanged);
    watcher.Created += new FileSystemEventHandler(OnChanged);
    watcher.Deleted += new FileSystemEventHandler(OnChanged);
    watcher.Renamed += new RenamedEventHandler(OnRenamed);

    watcher.IncludeSubdirectories = true;

    watcher.EnableRaisingEvents = true;

    while (true)
    {
    }
}

private static void OnRenamed(object sender, RenamedEventArgs e)
{
    Console.WriteLine($"OnRenamed: {e.FullPath}, {e.OldFullPath}");
}

private static void OnChanged(object sender, FileSystemEventArgs e)
{
    Console.WriteLine($"OnChanged: {e.ChangeType}, {e.Name}[{e.FullPath}]");
}
Sign up to request clarification or add additional context in comments.

8 Comments

My test above has the IncludeSubdirectories set to true and I still get the missing file path on the OnDeleted event if the OnChanged event is wired up.
@JM Could you please be more specific about your OS and .NET version? It works for me with Win10 and .NET Framework 4.7.1. I have included code I use.
My OS and .NET version are also Win 10 and .NET 4.7.1. I will run again to double check mine to be 100% sure. I will run yours too and compare.
@JM Your code works for me as well. Output: Watcher_Deleted <newline> C:\Temp\Root\subdir\test_file.txt <newline> Watcher_Changed <newline> C:\Temp\Root\subdir.
When I run yours I get: OnChanged: Created, subdir\New Text Document.txt[C:\test_dir\subdir\New Text Document.txt] OnChanged: Changed, subdir\New Text Document.txt[C:\test_dir\subdir\New Text Document.txt] OnChanged: Changed, subdir[C:\test_dir\subdir] OnChanged: Deleted, subdir\New Text Document.txt[C:\test_dir\subdir\New Text Document.txt] OnChanged: Changed, subdir[C:\test_dir\subdir]. That was for the creation of a text file followed by the deletion of the file.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.