I have this code to detect deleteing files.
m_Watcher = new System.IO.FileSystemWatcher();
m_Watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
m_Watcher.Changed += new FileSystemEventHandler(OnCreated);
m_Watcher.Created += new FileSystemEventHandler(OnChanged);
m_Watcher.Deleted += new FileSystemEventHandler(OnDeleted);
m_Watcher.Renamed += new RenamedEventHandler(OnRenamed);
m_Watcher.EnableRaisingEvents = true;
private void OnDeleted(object sender, FileSystemEventArgs e)
{
Debug.WriteLine(e.FullPath);
}
private void OnChanged(object sender, FileSystemEventArgs e)
{
Debug.WriteLine(e.FullPath);
}
But when I delete multiple files using Shift it detects 1 file only.
I know that it should be corrected via WaitForChanged method but I have no clue how to implement it.
The classic code does not help https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.deleted(v=vs.110).aspx
Thanks for help!
I found working solution here
FileSystemWatcher - Pure Chaos (Part 1 of 2)
http://www.codeproject.com/Articles/58740/FileSystemWatcher-Pure-Chaos-Part-of
Related
I am trying to monitor all files created/deleted/renamed in a folder using FileSystemWatcher in a docker volume. It is picking up events on the root dir (most of the time) that is being watched but nothing in subdir triggers an event even though IncludeSubdirectories = true. The watcher is saved as a prop. How can I get it to watch the subdir and trigger on all events not just most?
public void StartMonitorService()
{
Watcher = new FileSystemWatcher(#"/var/lib/docker/volumes/monitor");
Watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
Watcher.Created += OnCreated;
Watcher.Deleted += OnDeleted;
Watcher.Renamed += OnRenamed;
Watcher.Filter = "";
Watcher.IncludeSubdirectories = true;
Watcher.EnableRaisingEvents = true;
}
I didn't quite solve my question, but I have a work around for anyone who might have had the same issue I did.
private void OnCreated(object sender, FileSystemEventArgs e)
{
if (Directory.Exists(e.FullPath))
{
string dirRoot = e.FullPath;
DateTime lastTimeWriten = Directory.GetLastWriteTime(dirRoot);
while (true)
{
Thread.Sleep(30000);
if (lastTimeWriten == Directory.GetLastWriteTime(dirRoot))
break;
lastTimeWriten = Directory.GetLastWriteTime(dirRoot);
}
HashSet<string> fileSet = new HashSet<string>(Directory.GetFileSystemEntries(dirRoot, "*", SearchOption.AllDirectories));
...
_messageService.SendNewSurveyMessage(newSurveyFileSet);
}
}
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.
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}]");
}
Is there some mechanism by which I can be notified (in C#) when a file is modified on the disc?
You can use the FileSystemWatcher class.
public void CreateFileWatcher(string path)
{
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
/* Watch for changes in LastAccess and LastWrite times, and
the renaming of files or directories. */
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e)
{
// Specify what is done when a file is changed, created, or deleted.
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
// Specify what is done when a file is renamed.
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
That would be System.IO.FileSystemWatcher.
Use the FileSystemWatcher. You can filter for modification events only.
I have written this code for watching files in my system, but its not alerting any modificationms in the folder or file. How can I achieve this? I am not understanding as it does not show any exceptions or errors.
static void Main(string[] args)
{
FileSystemWatcher();
}
public static void FileSystemWatcher()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"D:\watcher";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "*.*";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
Console.Read();
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.Name + " has changed");
}
I updated the code. The NotifyFilter needs to be expanded if you want to see new files added
static void Main(string[] args)
{
FileSystemWatcher();
}
public static void FileSystemWatcher()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"D:\temp";
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Filter = "*.*";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += Watcher_Created;
watcher.Renamed += Watcher_Renamed;
watcher.EnableRaisingEvents = true;
Console.Read();
}
private static void Watcher_Renamed(object sender, RenamedEventArgs e)
{
Console.WriteLine(e.Name + " has been renamed");
}
private static void Watcher_Created(object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.Name + " has been added");
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.Name + " has changed");
}
FileSystemWatcher.NotifyFilter Property
watcher.NotifyFilter <- is flag enum!
You need to write:
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
...
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
I'm using FileWatcher to monitor an xml file to track of changes. I just want to fire some method when the contents of the file is changed, file is re-named or even deleted.
Subscribing to Changed event is enough for this?
Do I need to subscribe to other events as well?
In order to monitor all actions you want, you must listen to all event: create, change, delete, update.
Here's the sample:
public void init() {
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = "path/to/file";
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite | NotifyFilters.FileName
| NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = "*.txt";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// Begin watching.
watcher.EnableRaisingEvents = true;
}
// Define the event handlers.
private static void OnChanged(object source, FileSystemEventArgs e) {
// Specify what is done when a file is changed, created, or deleted.
}
private static void OnRenamed(object source, RenamedEventArgs e) {
// Specify what is done when a file is renamed.
}