I have this code, which should keep richTextBox2 updated at all times with usedPath's contents, but it doesn't.
private void watch()
{
var usedPath = Path.Combine(Directory.GetCurrentDirectory(), "usedwords.txt");
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = usedPath;
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = "*.txt*";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private void OnChanged(object source, FileSystemEventArgs e)
{
string usedPath = Path.Combine(Directory.GetCurrentDirectory(), "usedwords.txt");
richTextBox2.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
}
Can someone help me figure out what I have wrong?
Problem 1: Your watcher.Path = path of a single file, which will cause error.
Solution: Look at this: Use FileSystemWatcher on a single file in C#
watcher.Path = Path.GetDirectoryName(filePath1);
watcher.Filter = Path.GetFileName(filePath1);
Problem 2: Accessing richTextBox2 in OnChanged() will cause cross-thread error
Solution: Use this:
private void OnChanged(object source, FileSystemEventArgs e)
{
Invoke((MethodInvoker)delegate
{
string usedPath = Path.Combine(Directory.GetCurrentDirectory(), "usedwords.txt");
richTextBox2.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
});
}
Problem 3: There may be error when trying to LoadFile while some other programs are writing to it.
(Possible) Solution: Put a Thread.Sleep(10) in before trying to LoadFile in OnChanged
private void OnChanged(object source, FileSystemEventArgs e)
{
Thread.Sleep(10);
Invoke((MethodInvoker)delegate
{
richTextBox1.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
});
}
My complete code:
public partial class Form1 : Form
{
string usedPath = #"C:\Users\xxx\Desktop\usedwords.txt";
public Form1()
{
InitializeComponent();
watch();
}
private void watch()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = Path.GetDirectoryName(usedPath);
watcher.Filter = Path.GetFileName(usedPath);
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private void OnChanged(object source, FileSystemEventArgs e)
{
Thread.Sleep(10);
Invoke((MethodInvoker)delegate
{
richTextBox1.LoadFile(usedPath, RichTextBoxStreamType.PlainText);
});
}
}
Related
I am reading directories and adding .ini files to listbox1 or lisbox2 depending what is inside.
private void Form1_Load(object sender, EventArgs e)
{
string rootdir = #"C:\Users\isaced1\Desktop\test"; //root directory of all projects
string[] files = Directory.GetFiles(rootdir, "*.ini", SearchOption.AllDirectories); //searches for specific .ini files in all directories whithin rood directory
//cycles through all .ini files and adds it to lsitbox1 or listbox2
foreach (string item in files)
{
string fileContents = File.ReadAllText(item); //reads all .ini files
const string PATTERN = #"OTPM = true"; //search pattern in .ini files
Match match = Regex.Match(fileContents, PATTERN, RegexOptions.IgnoreCase); //matches pattern with content in .ini file
if (match.Success)
{
listBox1.Items.Add(item); //if match is successfull places file in lisbox1
listBox1.ForeColor = Color.Green;
}
else
{
listBox2.Items.Add(item); //if match is unsuccessfull places file in lisbox2
listBox2.ForeColor = Color.Red;
}
}
}
Now I want to to continuously repeat the process. I tried to do timer, but I keep getting error "error CS0120: An object reference is required for the non-static field, method, or property". I understand that my private void Form1_Load has to be static, but I just dont know way around it.
My timer code
private static System.Timers.Timer aTimer;
public static void Main1()
{
// Create a timer and set a two second interval.
aTimer = new System.Timers.Timer();
aTimer.Interval = 1000;
// Hook up the Elapsed event for the timer.
aTimer.Elapsed += new ElapsedEventHandler(Form1_Load);
// Have the timer fire repeated events (true is the default)
aTimer.AutoReset = true;
// Start the timer
aTimer.Enabled = true;
}
Any suggestions, thanks.
Don't poll for new files (using a timer is inefficient), use events from the OS to tell you when files are created/updated/deleted etc.
https://learn.microsoft.com/en-us/dotnet/api/system.io.filesystemwatcher?view=net-6.0
static void Main()
{
using var watcher = new FileSystemWatcher(#"C:\path\to\folder");
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
watcher.Changed += OnChanged;
watcher.Created += OnCreated;
watcher.Deleted += OnDeleted;
watcher.Renamed += OnRenamed;
watcher.Error += OnError;
watcher.Filter = "*.txt";
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
Console.WriteLine("Press enter to exit.");
Console.ReadLine();
}
private static void OnChanged(object sender, FileSystemEventArgs e)
{
if (e.ChangeType != WatcherChangeTypes.Changed)
{
return;
}
Console.WriteLine($"Changed: {e.FullPath}");
}
private static void OnCreated(object sender, FileSystemEventArgs e)
{
string value = $"Created: {e.FullPath}";
Console.WriteLine(value);
}
private static void OnDeleted(object sender, FileSystemEventArgs e) =>
Console.WriteLine($"Deleted: {e.FullPath}");
private static void OnRenamed(object sender, RenamedEventArgs e)
{
Console.WriteLine($"Renamed:");
Console.WriteLine($" Old: {e.OldFullPath}");
Console.WriteLine($" New: {e.FullPath}");
}
private static void OnError(object sender, ErrorEventArgs e) =>
PrintException(e.GetException());
private static void PrintException(Exception? ex)
{
if (ex != null)
{
Console.WriteLine($"Message: {ex.Message}");
Console.WriteLine("Stacktrace:");
Console.WriteLine(ex.StackTrace);
Console.WriteLine();
PrintException(ex.InnerException);
}
}
Having a Form with only a comboBox:enter image description here
And a MyTest folder in drive D where you can find Folder1,Folder2,Folder3enter image description here
I want to watch any added .txt files in the folder MyTest and move them to the Folder1 if Folder1 is selected in the comboBox a.s.o.
public void CreateFileWatcher(string path)
{
FileSystemWatcher fsw = new FileSystemWatcher("D:\\MyTest");
fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
fsw.Changed += new FileSystemEventHandler(OnChanged);
fsw.Created += new FileSystemEventHandler(OnChanged);
fsw.Deleted += new FileSystemEventHandler(OnChanged);
fsw.Error += new ErrorEventHandler(OnError);
fsw.EnableRaisingEvents = true;
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
}
private static void OnError(object source, ErrorEventArgs e)
{
Console.WriteLine("The FileSystemWatcher has detected an error");
if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
{
Console.WriteLine(("The file system watcher experienced an internal buffer overflow: " + e.GetException().Message));
}
}
You can implement OnChanged event like below:
private void OnChanged(object sender, FileSystemEventArgs e)
{
string destFolder = Path.Combine(#"d:\", comboBox1.SelectedItem.ToString());
if (!Directory.Exists(destFolder))
{
Directory.CreateDirectory(destFolder);
}
string destFileName = Path.Combine(destFolder, new FileInfo(e.FullPath).Name);
try
{
File.Move(e.FullPath, destFileName);
}
catch (Exception ex)
{
Console.WriteLine("File move operation error:" + ex.Message);
}
}
this is how you move file as
string sourceFile = #"C:\Users\Public\public\test.txt";
string destinationFile = #"C:\Users\Public\private\test.txt";
// To move a file or folder to a new location:
System.IO.File.Move(sourceFile, destinationFile);
// To move an entire directory. To programmatically modify or combine
// path strings, use the System.IO.Path class.
System.IO.Directory.Move(#"C:\Users\Public\public\test\", #"C:\Users\Public\private");
}
I have a hidden share:
\\computername\Logs$
And I need to monitor file changes in that share.
I've decided to use FileSystemWatcher Class, but it doesn't raise any events. And it doesn't show any errors to me.
static void Main(string[] args)
{
FileWatcher fw = new FileWatcher(#"\\computername\Logs$", "*.*");
fw.Start();
}
class FileWatcher(string filePath, string mask)
{
FileSystemWatcher watcher;
watcher.Path = filePath;
watcher.Filter = mask;
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
watcher.Changed += Watcher_Changed;
watcher.Error += OnError;
public void Start()
{
watcher.InternalBufferSize = 64 * 1024;
watcher.EnableRaisingEvents = true;
Console.WriteLine("Watcher Started");
while (!Console.KeyAvailable)
{
Thread.Sleep(1000);
}
}
private void Watcher_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine("File Changed");
}
private void OnError(object sender, ErrorEventArgs e)
{
Console.WriteLine("Error");
}
}
Does FileSystemWatcher work properly with hidden shares?
This code will not compile ,maybe you had errors while copy the code
and where the event handler Watcher_Changed, maybe you have mistake and put Watcher_Created instead
Hello All,
//Pleas i have a simple Problem. I need, when Filesystemwatcher sees the File -after fsw start the Timer for Closing Application (Application will be Closed after 2 second, when is file created)//
Thank you user "Never Quit" *
Finaly i Have this "easy" Code :-)
public partial class Form1 : Form
{
System.Timers.Timer casovac = new System.Timers.Timer();
int totalSeconds = 0;
public Form1()
{
InitializeComponent();
casovac.Interval = 1000;
casovac.Elapsed += new System.Timers.ElapsedEventHandler(cas_elapsed);
}
void cas_elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
totalSeconds++;
if (totalSeconds == 3)
{
casovac.Stop();
Application.Exit();
}
}
private void Form1_Load(object sender, EventArgs e)
{
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = Application.StartupPath + "\\OUT\\";
fsw.Filter = "file.exe";
fsw.IncludeSubdirectories = true;
fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
fsw.Changed += new FileSystemEventHandler(fsw_changed);
fsw.Created += new FileSystemEventHandler(fsw_changed);
fsw.EnableRaisingEvents = true;
}
private void fsw_changed(object source, FileSystemEventArgs e)
{
casovac.Start();
}
}
}
But Thank you All ;-)
I think you want to create one FileSystemWatcher which monitors your specified path and gives you an event when it founds "file.exe". As soon your program found this file timer get started and after several time(2 sec) your application get closed automatically. Right???
I've made demo which fulfill your requirement.
public partial class Form1 : Form
{
System.Timers.Timer tim = new System.Timers.Timer();
int totalSeconds = 0;
public Form1()
{
InitializeComponent();
tim.Interval = 1000; // 1 sec
tim.Elapsed += new System.Timers.ElapsedEventHandler(tim_Elapsed);
}
void tim_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
// .....
totalSeconds++;
if (totalSeconds == 2) // 2 sec of wait
{
tim.Stop();
Application.Exit();
}
}
private void Form1_Load(object sender, EventArgs e)
{
FileSystemWatcher fsw = new FileSystemWatcher("D:\\");
fsw.IncludeSubdirectories = true;
fsw.Filter = "file.exe";
fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
fsw.Changed += new FileSystemEventHandler(OnChanged);
fsw.Created += new FileSystemEventHandler(OnCreated);
fsw.Deleted += new FileSystemEventHandler(OnDeleted);
fsw.Renamed += new RenamedEventHandler(OnRenamed);
fsw.EnableRaisingEvents = true;
}
private void OnChanged(object source, FileSystemEventArgs e)
{
// Show that a file has been changed
WatcherChangeTypes wct = e.ChangeType;
MessageBox.Show("OnChanged File " + e.FullPath + wct.ToString());
tim.Start();// start timer as you get file.exe found....
}
private void OnCreated(object source, FileSystemEventArgs e)
{
// Show that a file has been created
WatcherChangeTypes wct = e.ChangeType;
MessageBox.Show("OnCreated File " + e.FullPath + wct.ToString());
tim.Start();// start timer as you get file.exe found....
}
private void OnDeleted(object source, FileSystemEventArgs e)
{
// Show that a file has been deleted.
WatcherChangeTypes wct = e.ChangeType;
MessageBox.Show("OnDeleted File " + e.FullPath + wct.ToString());
tim.Start();// start timer as you get file.exe found....
}
// This method is called when a file is renamed.
private void OnRenamed(object source, RenamedEventArgs e)
{
// Show that a file has been renamed.
WatcherChangeTypes wct = e.ChangeType;
MessageBox.Show("OnRenamed File " + e.OldFullPath + e.FullPath + wct.ToString());
tim.Start(); // start timer as you get file.exe found....
}
}
Hope this will help you....
I am trying to monitor a directory for new files in it with the FileSystemWatcher Class.
My Problem is that the event doesn't get triggered. My watcher class is:
public class Filewatcher
{
private FileSystemWatcher watcher;
public Filewatcher(string path, string filefilter)
{
this.watcher = new FileSystemWatcher();
this.watcher.Path = path;
this.watcher.NotifyFilter = NotifyFilters.FileName; //| NotifyFilters.LastWrite | NotifyFilters.LastAccess
this.watcher.Filter = filefilter;
this.watcher.Created += new FileSystemEventHandler(OnChanged);
}
public void start_watching()
{
//this.watcher.IncludeSubdirectories = true;
this.watcher.EnableRaisingEvents = true;
Console.WriteLine("Press Enter to quit\r\n");
Console.ReadLine();
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
//FileInfo objFileInfo = new FileInfo(e.FullPath);
//if (!objFileInfo.Exists) return;
Console.WriteLine("got the change\r\n");
global_functions.perform_action(Global_Vars.thereader.read(e.FullPath), Global_Vars.thepattern);
}
}
Operating System is Win 7 Prof x64
You don't make a call to start_watching(). Add a call to that and it may work better.