problem with fileSystemWatcher - c#

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().

Related

Xamarin Forms FileSystemWatcher

i need to watch a folder that are inside my ios/android application.
I would like to use FileSystemWatcher.
This is my code:
var DocFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
var InboxFolder = DocFolder + "/Inbox";
FileSystemWatcher watcher = new FileSystemWatcher() {
Path = InboxFolder,
NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName,
Filter = "*.*",
EnableRaisingEvents = true
};
watcher.Created += (object sender, FileSystemEventArgs e) => {
// do stuff
};
When the FileSystemWatcher is initializated this error is triggered:
System.NotImplementedException: The method or operation is not implemented.
How can I make this works?
There is another way to watch a folder?
Thank you!
FileSystemWatcher is a .NET Framework-based class which is currently not implemented in Xamarin, although the API is available in .NET Standard 2.0.
In UWP you can create a StorageFolderQuery with ContentChanged event handler to observe changes in a given folder. See documentation here.
Android has it's own alternative implementation in the form of Android.OS.FileObserver.
iOS does not seem to have anything out of the box, so this will probably either require you to find a library that does this job for you or to implement such functionality yourself, albeit in a less efficient manner than if it were built-in to the SDK.

C#: FileSystemWatcher only dispatches ChangedEvent

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.

FileSystemWatcher IncludeSubdirectories not working on network share

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.

Is it possible to watch a file, to see when it is being read?

I have a file, it is large, reading it takes a long time and I'd like to have some monitoring to see when it's being written to.
I can solve this quite easily by chucking some logging into the application that it reading it, however I'd like something more agnostic. There are quite a few application that have a similar use case. Monitoring writes should be easy enough as I can watch the last modified date, but reading isn't so easy.
If there any way to passively monitor read and writes to a file?
To clarify: If it can do done in 100% C#, then great, if not then shelling out to some other 'thing', or even resorting to some other language is fine. I don't really mind what the watching bit is written in.
Trying Rahul's Solution
I have set up ithe following test code. It dumps events to the console:
public static void Main()
{
var taskFactory = new TaskFactory();
var setup = new Action(() =>
{
var setupWatcher =
new Action<NotifyFilters, string, FileSystemWatcher>((filters, s, watcher) =>
{
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = filters;
watcher.Changed += (sender, args) => System.Console.WriteLine(s, args.FullPath, args.ChangeType);
});
var lastAccessWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.LastAccess,
"File: {0}\tFilter: LastAccess\tType: {1}", lastAccessWatcher);
var lastWriteWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.LastWrite, "File: {0}\tFilter: LastWrite\tType: {1}",
lastWriteWatcher);
var fileNameWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.FileName,
"File: {0}\tFilter: FileName\tType: {1}", fileNameWatcher);
var directoryNameWatcher = new FileSystemWatcher(BASE_PATH);
setupWatcher(NotifyFilters.LastWrite, "File: {0}\tFilter: DirectoryName\tType: {1}",
directoryNameWatcher);
});
taskFactory.StartNew(setup);
while (true)
{
Thread.Sleep(10);
}
}
However, when I open a text file in notepad, no event is thrown by the lastAccessWatcher, whereas, when I save, two events are thrown by the lastWriteWatcher and the directoryNameWatcher, as per below.
File: F:\FileMonitor\New Text Document.txt Filter: LastWrite Type: Changed
File: F:\FileMonitor\New Text Document.txt Filter: LastWrite Type: Changed
File: F:\FileMonitor\New Text Document.txt Filter: DirectoryName Type: Changed
File: F:\FileMonitor\New Text Document.txt Filter: DirectoryName Type: Changed
So...
What does trigger 'last access'
Can I actually have any trigger fired when a file is read?
For watching writes to the file, the FileSystemWatcher class is the right way to go. However if you want to know if a file is being written, what I would do is get a list of all the open files by process, and monitor when the file is opened and then closed.
There is a CodeProject article that shows how to get the open files by process here.
One solution would be to use a Microsoft tool called Process Monitor. It's able to list all CreateFile/ReadFile/WriteFile calls any process does. There are several command line options available:
You can use the FileSystemWatcher class
Listens to the file system change notifications and raises events when
a directory, or file in a directory, changes.
You can use the different events
Changed
Created
Deleted
Renamed
and also read this FileSystemWatcher Tips
An example:
public void MyFileWatcher(string path)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "myFile.txt";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
Console.WriteLine(e.FullPath + " " + e.ChangeType);
}
Similarly you can add other event handlers definition.
Also if you want to check the read then you can use the FileInfo.LastAccessTime and FileInfo.Refresh() in a polling loop to get the information of when your file is being read.
In code your task is handled with a filesystem filter driver. Process Monitor application (already mentioned in another answer) includes such driver in pre-built form.
You can write a kernel-mode driver yourself, yet this would probably be an overkill. Then there exists our CallbackFilter - a class library with a pre-created kernel-mode driver included. You write code in C# and catch all filesystem operations before or after they are performed. If your need is short-term, then the evaluation license will work.

FileSystemWatcher gets subdirectory events even though IncludeSubdirectories is set to false

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.

Categories