42

For some reason, my FileSystemWatcher is not firing any events whatsoever. I want to know any time a new file is created, deleted or renamed in my directory. _myFolderPath is being set correctly, I have checked.

Here is my current code:

public void Setup() {
    var fileSystemWatcher = new FileSystemWatcher(_myFolderPath);
    fileSystemWatcher.NotifyFilter = NotifyFilters.LastAccess | 
      NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

    fileSystemWatcher.Changed += FileSystemWatcherChanged;
    fileSystemWatcher.Created += FileSystemWatcherChanged;
    fileSystemWatcher.Deleted += FileSystemWatcherChanged;
    fileSystemWatcher.Renamed += FileSystemWatcherChanged;

    fileSystemWatcher.Filter = "*.*";
    fileSystemWatcher.EnableRaisingEvents = true;
}

private void FileSystemWatcherChanged(object sender, FileSystemEventArgs e)
{
    MessageBox.Show("Queue changed");
    listBoxQueuedForms.Items.Clear();
    foreach (var fileInfo in Directory.GetFiles(_myFolderPath, "*.*", SearchOption.TopDirectoryOnly))
    {
        listBoxQueuedForms.Items.Add(fileInfo));
    }
}
gwin003
  • 7,432
  • 5
  • 38
  • 59
  • What have you done to verify that a situation occurs in which those events should fire? – tnw Apr 29 '13 at 12:37
  • I have manually created, renamed and deleted files in my directory. Nothing fires. – gwin003 Apr 29 '13 at 12:37
  • Local drive, its an AppData/Roaming folder to be more specific – gwin003 Apr 29 '13 at 12:39
  • Are you sure `_myFolderPath` is the correct path? Because your code seems quite okay, fairly similar to the sample at http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.notifyfilter.aspx – pyrocumulus Apr 29 '13 at 12:39
  • Check out the [sample code here](http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.enableraisingevents.aspx), try that – tnw Apr 29 '13 at 12:40
  • The code definitely looks like it should work... I guess you must have run it under the debugger to verify the path. – Matthew Watson Apr 29 '13 at 12:42
  • `_myFolderPath` is correct, @sharpcloud. I have been using that sample code, @tnw. I am debugging now. I have 2 projects within the same solution, one project is a dll library I am building that has the `FileSystemWatcher` in it, the other just launches the form in the dll library. When the non-library project references my dll from the GAC, it doesnt seem to work. But when it references my other project, it works... I am looking into it still and will report back once I have a solution. – gwin003 Apr 29 '13 at 12:50

6 Answers6

48

You seem to be creating the FileSystemWatcher as a local variable in the setup method. This will of course go out of scope at the end of the method and may well be getting tidied up at that point, thus removing the watches.

Try creating the FSW at a point where it will be persisted (eg a program level variable) and see if that sorts you out.

Chris
  • 27,210
  • 6
  • 71
  • 92
  • 1
    I moved the `FileSystemWatcher` to a private local variable and it seems to be working more consistently now. – gwin003 Apr 29 '13 at 13:25
  • @gwin003 It _was_ a local variable. I suspect you mean that you moved it to a private _field_? – Fredrik Mörk Apr 29 '13 at 13:31
  • 1
    Oops, yeah thats what I meant haha. It wont let me edit my comment now for some reason... – gwin003 Apr 29 '13 at 13:33
  • 3
    You can only edit comments for a limited amount of time afterwards (5 mins I think). Glad that helped though. Another point to note with FSW is that they can't fire events on networked drives. Not relevant for you now from the comments above but a big gotcha if you ever do want to. :) – Chris Apr 29 '13 at 14:50
  • @adospace: http://stackoverflow.com/questions/298261/do-event-handlers-stop-garbage-collection-from-occuring – Chris Aug 04 '16 at 13:01
  • @Chris I've been trying to make a FSW work for two hours and just saw your comment about it not working on networked drives. Bingo. Thanks so much! – BittermanAndy Sep 05 '18 at 22:48
32

My problem was that I expected certain actions to cause the FileSystemWatcher Changed event to fire. For example, moving a file (clicking and dragging) from the desktop to the watched location did not raise an event but copying an existing file and pasting a new copy of it (there by creating a new file to the file system and not simply moving an existing one) caused the Changed event to be raised.

My solution was to add every NotifyFilter to my FileSystemWatcher. This way I am notified in all cases where the FileSystemWatcher is able to notify me.

NOTE that it isn't entirely intuitive/obvious as to which filters will notify you for specific cases. For example, I expected that if I included FileName that I would be notified of any changes to an existing file's name...instead Attributes seem to handle that case.

watcher.NotifyFilter = NotifyFilters.Attributes |
    NotifyFilters.CreationTime |
    NotifyFilters.FileName |
    NotifyFilters.LastAccess |
    NotifyFilters.LastWrite |
    NotifyFilters.Size |
    NotifyFilters.Security;
MoMo
  • 8,149
  • 3
  • 35
  • 31
30

Use this setter to enable the trigger:

watcher.EnableRaisingEvents = true;
Luca Ziegler
  • 3,236
  • 1
  • 22
  • 39
  • 9
    Oh my, thanks so much for that. Amazes me that that a flag is required for events. – David Haxton Apr 26 '17 at 16:47
  • 6
    Oh, wow... That took an hour of my life :/ Strange choice to set it to `false` by default. Aren't the events like a primary thing why you'd want to use the `FileSystemWatcher` in the first place? – the berserker Feb 09 '19 at 12:22
  • 4
    @theberserker, i think defaulting to false is the wisest choice because one may want to setup the watcher at a given time but only enable it after doing other setup work. – osiris Jan 05 '21 at 11:20
  • I appreciate you posting this even though the OP had it in their code already. It definitely helps the rest of us that didn't notice the requirement. – Bill Tarbell Dec 28 '21 at 20:04
0

My issue was that I expected it watches subdirectories also but it doesn't do it by default. If you would like to monitor also subdirectories then set IncludeSubdirectories property to true (it's false by default):

fileSystemWatcher.IncludeSubdirectories = true;
Anatolii Humennyi
  • 1,807
  • 3
  • 26
  • 37
0

I had the same issue in that a move or copy paste of a file would not trigger the file watcher. However, if I renamed or altered the file within the directory it worked. I reviewed documentation (https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-7.0) and it did not jump out what could cause this issue. Finally, there was a hint that maybe folder security because I read about how folder security could be different. I then went into folder security and the advanced settings. I gave permissions to Auditing to my user account. I also added my user account to Effective Access. Then, it all worked. I could move and cut/paste the file. Filewatcher now responded. This is what made the difference for me.

Randy Kroeger
  • 74
  • 1
  • 2
-2

We just had a very similar problem, where moving a folder did not trigger the expected events. The solution was to hard copy the entire folder, rather than just moving it.

DirectoryCopy(".", ".\\temp", True)

Private Shared Sub DirectoryCopy( _
        ByVal sourceDirName As String, _
        ByVal destDirName As String, _
        ByVal copySubDirs As Boolean)

        ' Get the subdirectories for the specified directory.
        Dim dir As DirectoryInfo = New DirectoryInfo(sourceDirName)

        If Not dir.Exists Then
            Throw New DirectoryNotFoundException( _
                "Source directory does not exist or could not be found: " _
                + sourceDirName)
        End If

        Dim dirs As DirectoryInfo() = dir.GetDirectories()
        ' If the destination directory doesn't exist, create it.
        If Not Directory.Exists(destDirName) Then
            Directory.CreateDirectory(destDirName)
        End If
        ' Get the files in the directory and copy them to the new location.
        Dim files As FileInfo() = dir.GetFiles()
        For Each file In files
            Dim temppath As String = Path.Combine(destDirName, file.Name)
            file.CopyTo(temppath, False)
        Next file

        ' If copying subdirectories, copy them and their contents to new location.
        If copySubDirs Then
            For Each subdir In dirs
                Dim temppath As String = Path.Combine(destDirName, subdir.Name)
                DirectoryCopy(subdir.FullName, temppath, true)
            Next subdir
        End If
    End Sub
Jonas_Hess
  • 1,874
  • 1
  • 22
  • 32