My FileSystemWatcher isn't throwing any events. I've looked at these similar questions, none seem to be an answer for my problem:
*Edit: My goal is to capture when an XLS file is copied to or created in a directory.
Filesystemwatcher doesn't trigger event
FileSystemWatcher - event not firing the second time
FileSystemWatcher Changed event doesn't fire
FileSystemWatcher - only the change event once firing once?
Monitor class:
public class Monitor
{
FileSystemWatcher watcher = new FileSystemWatcher();
readonly string bookedPath = #"\\SomeServer\SomeFolder\";
public delegate void FileDroppedEvent(string FullPath);
public event FileDroppedEvent FileDropped;
public delegate void ErrorEvent(Exception ex);
public event ErrorEvent Error;
public Monitor()
{
watcher.Path = bookedPath;
watcher.Filter = "*.xls";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed += new FileSystemEventHandler(watcher_Changed);
watcher.Error += new ErrorEventHandler(watcher_Error);
}
void watcher_Error(object sender, ErrorEventArgs e)
{
Error(e.GetException());
}
void watcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Created) return;
FileDropped(e.FullPath);
}
public void Start()
{
watcher.EnableRaisingEvents = true;
}
public void Stop()
{
watcher.EnableRaisingEvents = false;
}
}
Simple form with Listbox:
public partial class Form1 : Form
{
Monitor monitor = new Monitor();
public Form1()
{
InitializeComponent();
FormClosing += new FormClosingEventHandler(Form1_FormClosing);
Load += new EventHandler(Form1_Load);
monitor.FileDropped += new Monitor.FileDroppedEvent(monitor_FileDropped);
monitor.Error += new Monitor.ErrorEvent(monitor_Error);
}
void Form1_Load(object sender, EventArgs e)
{
monitor.Start();
}
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
monitor.Stop();
}
void monitor_Error(Exception ex)
{
listBox1.Items.Add(ex.Message);
}
void monitor_FileDropped(string FullPath)
{
listBox1.Items.Add(FullPath);
}
}
What am I doing wrong?
Try this out. Works for me for a very similar task.
watcher.NotifyFilter = NotifyFilters.FileName;
watcher.Created += new FileSystemEventHandler(handler);
watcher.Renamed += new RenamedEventHandler(handler);
This may be because the file metadata hasn't been updated yet. This may happen if you are continuously writing to the file.
Have you tried the following:
watcher.Path = directory name;
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "*.xls";
watcher.Changed += OnDirectoryChange;
watcher.Error += OnError;
watcher.EnableRaisingEvents = true;
// Watch only files not subdirectories.
watcher.IncludeSubdirectories = false;
Your issue is with the filters as well as your events I believe. NotifyFilters.LastAccess will only trigger when a file is opened. Try using:
NotifyFilters.LastWrite | NotifyFilters.CreationTime
This will watch for written/created files. Next, hook up to the Created delegate to handle newly created files:
watcher.Created += YourDelegateToHandleCreatedFiles
The way FileSystemWatcher works is to first use the NotifyFilters to limit the event triggers. Then, you use the actual events to do the work. By hooking into the Created event you'll only do work when a file is created.
Related
This question already has answers here:
FileSystemWatcher Changed event is raised twice
(44 answers)
Closed 6 years ago.
public void startWatch()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = Path.GetDirectoryName(_file);
watcher.Filter = Path.GetFileName(_file);
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed += watcher_Changed;
watcher.EnableRaisingEvents = true;
}
public void watcher_Changed(object sender, FileSystemEventArgs e)
{
// Jump twice
}
Why this event jump twice after my text file changed?
Here is the sample to avoid event raising.
public void OnChanged(object source, FileSystemEventArgs e)
{
FileSystemWatcher watcher = null;
try
{
watcher = (FileSystemWatcher)source;
watcher.EnableRaisingEvents = false;
}
finally
{
if (watcher != null)
{
watcher.EnableRaisingEvents = true;
}
}
}
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.
}
i like to add controls inside the form1 where a event handler for
watcher.Changed += new FileSystemEventHandler(OnChanged); is defined , is it possible to add control for example list box to the form1 but need to be added inside the event handler where it is defined
/*event added*/
private void btn_start_Click(object sender, EventArgs e)
{
string[] args = {this.txtfolder.Text};
if (args.Length != 1)
{
// Display the proper way to call the program.
Console.WriteLine("Usage: Invalid Operation");
return;
}
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[0];
/* 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 = this.txtfilter.Text;//"*.txt";
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
// watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
// 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);
// Form1 F ;
// ListBox lst = new ListBox();
//lst.Items.Add("File: " + e.FullPath + " " + e.ChangeType.ToString());
//f.lsttracker.Items.Add("File: " + e.FullPath + " " + e.ChangeType.ToString());
// F.controls.Add(lst);
This is what your looking for. From what you commented out, you probably didn't set the location and size, thus adding the control probably wasn't working. But you should really make sure to regulate this and make sure you are only adding controls exactly when you want to and no more.
private static void OnChanged(object source, FileSystemEventArgs e)
{
ListBox toAdd = new ListBox();
toAdd.Location = new Point(20,20);
toAdd.Size = new Size(200,200);
this.Controls.Add(toAdd);
}
If you want to store the controls you added, try something like this:
private List<Control> AddedItems = new List<Controls>();
private int OffsetY = 0;
private static void OnChanged(object source, FileSystemEventArgs e)
{
ListBox toAdd = new ListBox();
if(AddedItem.Last().Point.Y == OffsetY) // just an example of reusing previously added items.
{
toAdd.Location = new Point(20, OffsetY);
toAdd.Size = new Size(200,200);
AddedItems.Add(toAdd);
this.Controls.Add(toAdd);
}
OffsetY += 200;
}
EDIT: In reply to what you mentioned in the comment below.
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
private void btn_start_Click(object sender, EventArgs e)
{
string FolderPath = this.txtfolder.Text;
string Filter = this.txtfilter.Text;
if(!Directory.Exists(FolderPath))
{
Console.WriteLine("Not a valid directory"); //checks directory is valid
return;
}
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = FolderPath;
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
// Only watch filter files.
watcher.Filter = Filter;
watcher.IncludeSubdirectories = true; //monitor subdirectories?
watcher.EnableRaisingEvents = true; //allows for changed events to be fired.
// Add event handlers.
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
}
//Delegate to get back to UI thread since OnChanged fires on non-UI thread.
private delegate void updateListbox(string context);
private void OnChanged(object source, FileSystemEventArgs e)
{
this.Invoke(new updateListbox(UpdateListbox), "File: " + e.Name);
this.Invoke(new updateListbox(UpdateListbox), ">>Action: " + e.ChangeType);
this.Invoke(new updateListbox(UpdateListbox), ">>Path: " + e.FullPath);
}
public void UpdateListbox(string context)
{
lsttracker.Items.Add(context);
}
So, I'm trying to make a file changed notifier, and I need to make it so the text in a textbox updates whenever the contents of the file are changed. This is what I have so far:
string path = "C:/Users/Max/Dropbox/Public/IM.txt";
StringBuilder b = new StringBuilder();
private void Window_Loaded(object sender, EventArgs e)
{
TB.Text = File.ReadAllText(path);
b.Append(TB.Text);
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path.Remove(path.Length - 6, 6);
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "*.txt";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
TB.SelectionStart = TB.Text.Length;
TB.ScrollToCaret();
}
private void OnChanged(object source, FileSystemEventArgs e)
{
TB.Text = File.ReadAllText(path);
}
This seems to raise the event correctly, but as soon as it touches the code in the OnChanged event, the program exits, no errors or anything, just closes. I have tried to stop it from closing, I have even tried putting e.Cancel under the formclosing event, but nothing seems to work. Any ideas? I can provide more info if needed.
Have you tried wrapping the code in try catch
private void OnChanged(object source, FileSystemEventArgs e)
{
try
{
TB.Text = File.ReadAllText(path);
}catch(Exception e)
{
//Show exception in messagebox or log to file.
}
}
Try this in your Changed method
if (TB.InvokeRequired)
{
TB.Invoke(new MethodInvoker(delegate { TB.Text = File.ReadAllText(path); }));
}
I wanna show a dialog everytime some file has been changed... But everytime that dialog shows up, my app freeze. How can I do this with another thread? Any ideas?
protected virtual void CreateWatcher (object path)
{
if (watcher != null)
{
watcher.EnableRaisingEvents = false;
watcher.Dispose ();
}
//Create a new FileSystemWatcher.
watcher = new FileSystemWatcher ();
//Set the filter to only catch TXT files.
watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;
watcher.NotifyFilter = NotifyFilters.LastWrite;
//Subscribe to the Created event.
watcher.Changed += new FileSystemEventHandler (OnChanged);
watcher.Created += new FileSystemEventHandler (OnChanged);
//watcher.Deleted += new FileSystemEventHandler (OnChanged);
//watcher.Renamed += new RenamedEventHandler (OnRenamed);
//Set the path to C:\\Temp\\
watcher.Path = #path.ToString();
//Enable the FileSystemWatcher events.
watcher.EnableRaisingEvents = true;
}
void OnChanged (object source, FileSystemEventArgs e)
{
NovaInteracaoMsg();
}
protected virtual void NovaInteracaoMsg ()
{
novaInteracao = new MessageDialog (this, DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.YesNo, "Foi detectada a mudança nos arquivos do modelo. Deseja inserir uma nova interação?");
ResponseType result = (ResponseType)novaInteracao.Run ();
if (result == ResponseType.Yes) {
OpenInfoWindow (novaInteracaoPath);
return;
}
else {
novaInteracao.Destroy ();
}
}
void OnRenamed (object source, RenamedEventArgs e)
{
//Console.WriteLine ("File: {0} renamed to\n{1}", e.OldFullPath, e.FullPath);
}
protected virtual void OpenInfoWindow (string path)
{
ModMemory.Iteration iterWin = new ModMemory.Iteration (path);
iterWin.Modal = true;
iterWin.Show ();
iterWin.Destroyed += delegate {
// TODO: Funções para executar quando a janela for fechada
// Possivelmente atualizar o número de interações realizadas
Console.WriteLine ("Janela modal destruída");
};
}
The problem is that you are already using another thread. Try one of the following approaches
Set the FileSystemWatcher.SynchronizingObject property so it
raises events on your UI thread. Now you can show a UI that won't
freeze or
Use Control.BeginInvoke() in the event handler.
This was a psychic debugging attempt, there was nothing in your question that helped me be sure that's the correct answer.
Call Show() instead of ShowDialog() in your form.
http://msdn.microsoft.com/en-us/library/system.windows.forms.control.show.aspx
Edit - MessageBox classes are Modal, if you want a modeless dialog window you'll have to create it yourself.