I am working with the FileSystemWatcher construct in C#. As par for the course, I am making my watchers only watch directories of interests. The problem I am having is that regardless of the user event (copy, create, rename) the only event I am picking up is the Changed event.
For example.
Watch file "C:...\Desktop\MattsRequest"
Create File "C:...\Desktop\MattsRequest\Dummy.txt"
Observe that only the OnChanged handler is triggered with a FileSystemEventArg of "Changed" and the path arg is "C:...\Desktop\MattsRequest" and no mention of what file was created
My watcher code looks like so.
watcher = new FileSystemWatcher();
//watcher.IncludeSubdirectories = true;
watcher.InternalBufferSize = 32768 * 2;
//Can't use a synchro because I can't find an example of something that
//implements ISynchroniz-whatever
//watcher.SynchronizingObject =
watcher.Path = filePath;
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName
| NotifyFilters.CreationTime;
watcher.Changed += OnChanged; //Gets triggered
watcher.Created += OnCreated; //Never triggered
watcher.Deleted += OnDeleted;
watcher.Renamed += OnRenamed; //Never triggered
watcher.Error += WatcherOnError; //Never triggered
// Begin watching.
watcher.EnableRaisingEvents = true;
Below is an image of when I have created a new file in the watched directory, and the event that it fires off. It's of course of type Changed, but it doesn't tell me which file was created.
Any help is greatly appreciated.
This might happen when you watch a directory and create a file inside subdirectory of that directory. That is because creating a file in a directory changes that directory's timestamp, and that is the event you see (change of the directory).
To fix - either watch subdirectory itself, or set watcher.IncludeSubdirectories = true; to include subdirectories.
Evk's answer was the correct one. I was watching the grandparent folder only, and that folder fired off an event which was missing the information. Once I added a watcher to the parent folder, the Created and other events were fired off correctly.
Related
I am using below code to monitor changes happening in a directory including subdirectories. Currently, I am running three different copies of this application and two of them are working fine. Application for which it is not working contains more than 320K subdirectories in it.
I tried to increase InternalBufferSize but nothing happens.
It is working at the root folder and not working for any of the subdirectories.
Also, 2 other copies of the same application monitoring different network paths on different geographical locations are working fine including subdirectories as well.
FileSystemWatcher watcher = new FileSystemWatcher
{
Path = path,
IncludeSubdirectories = true,
Filter = "*.txt",
NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite |
NotifyFilters.FileName | NotifyFilters.DirectoryName
};
watcher.Created += Watcher_Created;
watcher.Changed += Watcher_Changed;
watcher.Deleted += Watcher_Deleted;
watcher.Renamed += Watcher_Renamed;
watcher.Error += Watcher_Error;
watcher.EnableRaisingEvents = true;
PS: Polling is not an option. It takes 3 days to scan entirely 320K directories.
The root-level folder has 2000 plus subdirectories and each subdirectory has up-to 8 levels of subfolders in it
Edit-1:I have checked with the INFRA team and got to know that shared folders are on EMC Isilon NAS storage.
https://social.msdn.microsoft.com/Forums/vstudio/en-US/38adb37d-bbfc-40d6-8b32-a5c1c7d8d4a3/are-there-any-limitations-of-filesystemwatcher-monitoring-a-unc-path-on-nas-server?forum=netfxbcl
Instead of executing the event handlers synchronously, it may help to offload them to the ThreadPool. This will minimize the risk of overflowing the internal buffer of the FileSystemWatcher. The Offload method below could be used for this purpose:
public static FileSystemEventHandler Offload(FileSystemEventHandler handler)
{
return (s, e) => ThreadPool.QueueUserWorkItem(_ => handler(s, e));
}
Usage example:
var fsw = new FileSystemWatcher(path);
fsw.Created += Offload((s, e) =>
{
Console.WriteLine($"Created: {e.Name}");
});
This is not intended as an efficient solution, but just as an easy fix to the buffer-overflow problem (assuming that it's the cause for the issues you are observing).
I'm attempting to watch a network share for folders where a file is added to the share to indicate the upload is complete. I wanted to use a FileSystemWatcher to monitor that share and its subdirectories for that trigger file, as shown below.
FileSystemWatcher fsw = new FileSystemWatcher(share, triggerFilePattern);
fsw.IncludeSubdirectories = true;
fsw.Created += new FileSystemEventHandler(OnCreated);
fsw.Renamed += new RenamedEventHandler(OnRenamed);
fsw.Error += new ErrorEventHandler(OnError);
If a file is created at the root of the share, the event triggers. If a file is created within a subdirectory of the share, the event does not trigger, and I don't get an error either.
If I create a new FileSystemWatcher for that subdirectory, then I do receive an event when a file is created there. But, similar to the top level FileSystemWatcher, I won't get events for files created in any further subdirectories.
If I change the network share to a local directory for testing, it does work as expected.
Any ideas? Could I have set up some wonky network share setting that blocks recursive FileSystemWatcher checks? I can work around this, but it would be nice to not have to complicate the code.
Edit: I saw that I didn't have Full Control under Properties->Security tab, so I thought that could be it. But I was able to get normal desired behavior on a different share with the same visible permissions, so I'm back to not knowing why this specific share isn't working.
Edit2: At a coworker's suggestion, I added a Changed handler too. Doesn't make sense to me how a file can be changed without getting Created first, but... I'm getting Changed events on the share in question when creating files in a subdirectory. (And I'm still getting nothing when renaming them.) This solves my immediate problem, but I'm going to leave the question open in case someone's able to answer why that's happening.
Try this
private static FileSystemWatcher fw;
static void Main(string[] args)
{
fw = new FileSystemWatcher(#"D:\Folder_Watch");
fw.IncludeSubdirectories = true;
fw.NotifyFilter = NotifyFilters.LastAccess |
NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
fw.Created += fw_Created;
fw.Changed += fw_Created;
fw.Renamed += fw_Created;
fw.Filter = "*.*";
fw.EnableRaisingEvents = true;
new System.Threading.AutoResetEvent(false).WaitOne();
}
static void fw_Created(object sender, FileSystemEventArgs e)
{
try
{
fw.EnableRaisingEvents = false;
//Your Code
}
finally
{
fw.EnableRaisingEvents = true;
}
}
I had same problem and I solved it by giving write permission to the shared network folder (it had only read permission so far). Shared folder is originally on Linux but I have it mounted on Windows Server 2008 R2 where I'm running program with FileSystemWatcher.
I have the following FileSystemWatcher setup in my windows service.
FileSystemWatcher Watcher = new FileSystemWatcher();
Watcher.Path = watcherDir;
Watcher.NotifyFilter = NotifyFilters.LastWrite;
Watcher.Renamed += Watcher_Renamed;
Watcher.Changed += Watcher_Changed;
Watcher.Error += Watcher_Error;
Watcher.Filter = "*.*";
Watcher.IncludeSubdirectories = false;
Watcher.EnableRaisingEvents = true;
I see some inconsistent behavior - it listens to changes in subdirectories too. I have logged to see what it finds it is bit odd.
I am watching C:\Temp\Folder1, and some other process creates a log file in C:\Temp\Folder1\Folder2. This FileSystemWatcher object is picking this info up -
1. e.FullPath gives the name of the subdirectory, in this case C:\Temp\Folder1\Folder2
2. Path.GetDirectoryName(e.FullPath) gives me the directory that I am actually watching for i.e. C:\Temp\Folder1.
3. The extension is empty and that is how I ignore this and this is how I ignore this case.
Any suggestions for how else I can figure out what is going on here?
The creation or deletion of a file within a directory is also counted as a change to that directory itself. That's the event that's being reported to you. Folder2, itself, is within the directory that you're monitoring.
The reported path is the path of the directory, not the file within it, and you'll notice that its your Changed handler being invoked, despite the fact that the file system operations are actually creation or deletion.
In your event handler, you could just check whether the reported path is a directory, and just return and perform no further processing in the event handler, if that's the case.
I've created simple WPF control to monitor changes in log file. I used FileSystemWatcher to watch specific file. My configuration:
Directory = System.IO.Path.GetDirectoryName(logFileFullPath);
Filter = System.IO.Path.GetFileName(logFileFullPath);
NotifyFilter = (NotifyFilters.LastWrite | NotifyFilters.Size);
EnableRaisingEvents = true;
The problem is that changes are displayed only after refreshing the directory manually or opening log file.
I use RollingFileAppender in my log4net configuration so changes should be written immediately.
The question is: why dosn't it work and how to make it work?
EDIT :
Also when I update manually other monitored file the watcher works fine. So it must be some log4net issue.
I've finally come up with solution. The problem had little to do with FileSystemWatcher. My log4net configuration was lacking the line:
<lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
It's still quite interesting as I had no problem with opening log file from text editor.
Try this code,
FileSystemWatcher watcher = new FileSystemWatcher(#"logFileDirectoryPath");
watcher.Filter = "LogFileNameWithExtension";
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size;
watcher.Changed += new FileSystemEventHandler(watcher_Changed);
Changed Event
private void watcher_Changed(object sender, FileSystemEventArgs e)
{
//Do Something
}
I have two applications, CREATOR (which I can't modify) and OBSERVER. CREATOR manipulates many files, and I need OBSERVER to know when that happens. I wrote OBSERVER in C#, and I'm using FileSystemWatcher. I set path to my path, set filter to FILE and add all the necessary events. But when CREATOR modifies the file, no event is raised in OBSERVER. Oddly, when I modify the file by hand, OBSERVER does see the change. I thought that maybe CREATOR doesn't free the file, but when I close CREATOR, OBSERVER still doesn't see the change.
Any idea what I'm doing wrong?
Extra details:
When CREATOR modifies the file, I can delete it by hand, or when I open the file I see that all changes are saved.
edit
my fileSystemWatcher object setting:
fileSystemWatcherObs.EnableRaisingEvents = true;
fileSystemWatcherObs.Filter = "kbd.dbf";
fileSystemWatcherObs.IncludeSubdirectories = true;
fileSystemWatcherObs.NotifyFilter = NotifyFilters.FileName | NotifyFilters.LastWrite | NotifyFilters.Attributes |
NotifyFilters.CreationTime | NotifyFilters.DirectoryName |NotifyFilters.LastAccess | NotifyFilters.Security |
NotifyFilters.Size;
fileSystemWatcherObs.Path = "D:\\FOLDER";
fileSystemWatcherObs.SynchronizingObject = this;
fileSystemWatcherObs.Changed += new System.IO.FileSystemEventHandler( this.fileSystemWatcherObs_Changed );
fileSystemWatcherObs.Created += new System.IO.FileSystemEventHandler( this.fileSystemWatcherObs_Created );
fileSystemWatcherObs.Deleted += new System.IO.FileSystemEventHandler( this.fileSystemWatcherObs_Deleted );
fileSystemWatcherObs.Renamed += new System.IO.RenamedEventHandler( this.fileSystemWatcherObs_Renamed );
and of course method for this events
Here a few hints that maybe helps you:
It doesn't matter if you made the changes by hand or by another application "you CREATOR", since when you make them by hand, you actually use some application like "notepad.exe" or something, so that is not really matters.
You should set EnableRaisingEvent to true "start watching" after you set the path and register the event handlers, so the it should be last thing after set all the configurations of the watcher.
At your NotifyFilter are setting the whole notifications filters which will leads you to receive duplicates notifications some times.
Since you only want to watch a specific folder, then you don't have to include sub folders, i.e fIncludeSubdirectories should be false.
Why you are setting a SynchronizingObject to this? a better if you have to anyway is to take it to a new object().