How can get value of "FileSystemWatcher" in other loop function - c#

I have class "SystemWatchFile" used to detect a file change . Every a file changed so i can capture this change in function "OnChanged".
In other loop function i call to SystemWatchFile to monitor the change of file. Like below :
while (true)
{
SystemWatchFile watchfile = new SystemWatchFile(#" f:\Tutorial\C#\FileSytemWatcher\readme.txt");
watchfile.Run();
///at here , how can i get value from "OnChanged" , when a file is changed
}
I try use to delegate to implement callback but not work.My class :
public class SystemWatchFile
{
string FileNeedWatching = "";
bool let = false;
public SystemWatchFile(string file)
{
FileNeedWatching = file;
}
public void Run()
{
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
string filePath1 = FileNeedWatching;
watcher.Path = Path.GetDirectoryName(filePath1);
// Watch for changes in LastAccess and LastWrite times, and
// the renaming of files or directories.
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
// Only watch text files.
watcher.Filter = Path.GetFileName(filePath1);
// Add event handlers.
watcher.Changed += OnChanged;
// Begin watching.
watcher.EnableRaisingEvents = true;
}
}
private void OnChanged(object source, FileSystemEventArgs e)
{
if (let == false)
{
Console.WriteLine($"File: {e.FullPath} {e.ChangeType}");
let = true;
}
else
{
let = false;
}
}
}
How can i get value when file change ?

Related

How to track a specific file changes using MVVM pattern in .net?

I am working on a .NET WPF project using Visual Studio 2022 and I added tray icon functionality to my app. I am managing tray icon part in mainwindow.xaml.cs but i need to track file changes in my mainviewmodel class as well. How can i pass this event to mvvm or maybe pass data to mainviewmodel ? Any help would be appreciated.
public void CreateFileWatcher(string path)
{
watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Filter = nameof(AppStateModel);
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
}
private void OnChanged(object source, FileSystemEventArgs e)
{
Thread.Sleep(1000);
var appState = CheckAppState();
AppState = appState;
string workingDirectory = Environment.CurrentDirectory;
string projectDirectory = Directory.GetParent(workingDirectory).Parent.FullName;
var path = Path.Combine(projectDirectory, "Assets");
switch (appState)
{
case 1:
m_notifyIcon.Icon = new System.Drawing.Icon(Path.Combine(path, "48x48_active.ico"));
break;
case 2:
m_notifyIcon.Icon = new System.Drawing.Icon(Path.Combine(path, "48x48_inactive.ico"));
break;
case 4:
m_notifyIcon.Icon = new System.Drawing.Icon(Path.Combine(path, "48x48_running.ico"));
break;
default:
break;
}
}
private int CheckAppState()
{
try
{
var tempFile = Path.Combine(AppWizard.Default.FolderPath, nameof(AppStateModel));
if (!File.Exists(tempFile))
return -1;
var _path = tempFile;
using (var stream = new FileStream
(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
var appStateModel = JsonConvert.DeserializeObject<AppStateModel>(File.ReadAllText(tempFile));
if (appStateModel != null)
{
if (appStateModel.CurrentState == AppStates.Ready)
return 1;
else if (appStateModel.CurrentState == AppStates.Dead || appStateModel.CurrentState == AppStates.Expired)
return 2;
else if (appStateModel.CurrentState == AppStates.Busy)
return 4;
}
}
}
catch (Exception ex)
{
FileLogger.Default.WriteExceptionLog(ex);
}
return -1;
}
A watcher service may look as following:
public class FileWatcherService
{
FileSystemWatcher watcher;
public FileWatcherService()
{
CreateFileWatcher();
}
public event EventHandler<FileSystemEventArgs> FileChanged;
public void CreateFileWatcher()
{
watcher = new FileSystemWatcher(#"C:\Temp");
watcher.NotifyFilter = NotifyFilters.Attributes
| NotifyFilters.CreationTime
| NotifyFilters.DirectoryName
| NotifyFilters.FileName
| NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.Security
| NotifyFilters.Size;
watcher.Changed += MakeANote;
watcher.Created += MakeANote;
watcher.Deleted += MakeANote;
watcher.Renamed += MakeANote;
watcher.Filter = "*.*";
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
private void MakeANote(object sender, FileSystemEventArgs e)
{
FileChanged?.Invoke(this, e);
}
}
A simple way is to put the "watcher" in the View Model :
public class MainViewModel :Binding
{
FileWatcherService _fileWatcherService = new FileWatcherService();
public MainViewModel()
{
_fileWatcherService.FileChanged += OnFileChanged;
}
private void OnFileChanged(object sender, FileSystemEventArgs e)
{
LastAction = e.ChangeType.ToString();
File = e.Name;
}
string _lastAction;
public string LastAction
{
get { return _lastAction; }
set { _lastAction = value;NotifyPropertyChanged(nameof(LastAction)); }
}
string _file;
public string File
{
get { return _file; }
set { _file = value; NotifyPropertyChanged(nameof(File)); }
}
}
And the sample XAML code will be as following:
<Grid>
<Grid.DataContext>
<local:MainViewModel/>
</Grid.DataContext>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding File}"/>
<TextBlock Text=" has "/>
<TextBlock Text="{Binding LastAction}"/>
</StackPanel>
</Grid>

FilesSystemWatcher For each item in List, look at that file

Goal:
The main goal is to get all path names from MySQL, and use File System Watch to watch them paths for rename, deleted and created.
I have this full code here:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using MySql.Data.MySqlClient;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
Run();
}
public static void Run()
{
MySqlConnection mcon = new MySqlConnection("credentials");
MySqlDataReader myreader = null;
MySqlCommand cmd = new MySqlCommand("select * from files", mcon);
mcon.Open();
myreader = cmd.ExecuteReader();
List<String> list = new List<String>();
while (myreader.Read())
{
list.Add(myreader[1].ToString());
foreach (string i in list)
{
Console.WriteLine(i);
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = Path.GetDirectoryName($#"{i}");
watcher.Filter = Path.GetFileName($#"{i}");
watcher.EnableRaisingEvents = true;
watcher.IncludeSubdirectories = true;
watcher.Created += directoryChange;
watcher.Deleted += directoryChange;
watcher.Renamed += onRename;
Console.Read();
}
}
mcon.Close();
}
private static void directoryChange(object source, System.IO.FileSystemEventArgs e)
{
Console.WriteLine($"{e.ChangeType} - {e.FullPath} - {System.Environment.NewLine}");
}
private static void onRename(object source, RenamedEventArgs e)
{
Console.WriteLine($"{e.OldFullPath} renamed to {e.FullPath}");
}
}
}
And this is a table in MySQL:
ID Path
1 G:/Folder/EdGzi/Test purposes Python/file.txt
2 G:/Folder/EdGzi/Test purposes Python/test2.txt
Problem:
When I run this application. It watches only 1 file(only the top record only from MySQL data). Whereas, it should have been watching all the files returned from MySQL table.
That's why I have created the foreach code.
Question:
How can I do this?
Get rid of Console.Read from the loop, place it after the loop. That will Console.WriteLine(i); each record from MySQL table.
Like so:
public static void Run()
{
MySqlConnection mcon = new MySqlConnection("server=WINX-PC04;user id=root;password=GS201706;database=technical");
MySqlDataReader myreader = null;
MySqlCommand cmd = new MySqlCommand("select * from files", mcon);
mcon.Open();
myreader = cmd.ExecuteReader();
List<String> list = new List<String>();
while (myreader.Read())
{
list.Add(myreader[1].ToString());
}
mcon.Close();
foreach (string i in list)
{
Console.WriteLine(i);
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = Path.GetDirectoryName($#"{i}");
watcher.Filter = Path.GetFileName($#"{i}");
watcher.EnableRaisingEvents = true;
watcher.IncludeSubdirectories = true;
watcher.Created += directoryChange;
watcher.Deleted += directoryChange;
watcher.Renamed += onRename;
}
Console.Read(); // Likethis
}
You can given FileSystemWatcher objects only one directory and file extension.
You must create multiple FileSystemWatcher objects to monitor multiple different files. If you do this, you must c# lock statement each event.
This example follows the *.jpg extensions, including subdirectories in the target directory.
static void Main(string[] args)
{
// target main folder
string directoryName = #"E:\Apps\2019\SADtest\Decupe\SADtest\Veriler\sources\";
// such as only watch JPG files
string fileExtension = "*.jpg";
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
// NotifyFilter is Flag attribute.
// triggers when file names created, changed or updated.
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime | NotifyFilters.LastWrite;
watcher.Path = directoryName;
// the Filter propertie must contain wildcards or empty.
// you cannot write multiple extensions.
// all files : *.*
// only text : *.txt
// ends withs : *test2.txt
watcher.Filter = fileExtension;
// track the same extensions in all subdirectories.
watcher.IncludeSubdirectories = true;
// register events
watcher.Created += Watcher_Created;
watcher.Deleted += Watcher_Deleted;
watcher.Renamed += Watcher_Renamed;
// begin watching...
watcher.EnableRaisingEvents = true;
// sample message
Console.WriteLine("Press 'ENTER' to quit watching.");
Console.WriteLine($"I am watching the files with the '{fileExtension}' extension in the '{directoryName}' directory.");
// wait for the user to quit the program.
Console.WriteLine();
Console.Read();
}
}
private static void Watcher_Renamed(object sender, RenamedEventArgs e)
{
Console.WriteLine($"Renamed:File: {e.OldFullPath} renamed to {e.FullPath}");
}
private static void Watcher_Deleted(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"Deleted:File: {e.FullPath} {e.ChangeType}");
}
private static void Watcher_Created(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"Created:File: {e.FullPath} {e.ChangeType}");
}
Here is the console results :
Press 'ENTER' to quit watching.
I am watching the files with the '*.jpg' extension in the 'E:\Apps\2019\SADtest\Decupe\SADtest\Veriler\sources' directory.
Renamed:File: E:\Apps\2019\SADtest\Decupe\SADtest\Veriler\sources\meee.jpg renamed to E:\Apps\2019\SADtest\Decupe\SADtest\Veriler\sources\sener.jpg
Created:File: E:\Apps\2019\SADtest\Decupe\SADtest\Veriler\sources\logo2.jpg Created
Deleted:File: E:\Apps\2019\SADtest\Decupe\SADtest\Veriler\sources\logo2.jpg Deleted

Using file.move to rename new files in C#

I am very new to coding and I'm writing an application which will rename files
by appending milliseconds to the existing filename of files which have been scanned in from an MFD.
The folder is a shared folder and the renamed file should stay within it and not be copied elsewhere.
From doing a lot of searching, I know that File.Move is my way forward, however, I can't seem to get it to work.
Here's my code:
private void MonitorToggle_Click(object sender, EventArgs e)
{
// Create a new FileSystemWatcher object.
FileSystemWatcher fsWatcher = new FileSystemWatcher();
switch (MonitorToggle.Text)
{
// Start Monitoring…
case startMonitoring:
if (!FilePathField.Text.Equals(String.Empty))
{
//Set the watched folder path equal to the file path variable
fsWatcher.Path = FilePathField.Text;
// Set Filter.
fsWatcher.Filter = (FileTypeField.Text.Equals(String.Empty))? "*.*" : FileTypeField.Text;
// Monitor files and subdirectories.
fsWatcher.IncludeSubdirectories = true;
// Monitor all changes specified in the NotifyFilters.
fsWatcher.NotifyFilter = NotifyFilters.LastWrite;
fsWatcher.EnableRaisingEvents = true;
// Raise Event handlers.
fsWatcher.Changed += new FileSystemEventHandler(OnChanged);
fsWatcher.Created += new FileSystemEventHandler(OnCreated);
}
else
{
MessageBox.Show("Please select a folder to monitor.", "Warning",MessageBoxButtons.OK, MessageBoxIcon.Warning );
}
break;
// Stop Monitoring…
case stopMonitoring:
default:
fsWatcher.EnableRaisingEvents = false;
fsWatcher = null;
break;
}
}
public void OnChanged (object sender, FileSystemEventArgs e)
{
FileInfo file = new FileInfo(e.Name);
string dateStamp = DateTime.Now.ToString("fff");
string fName = file.Name;
string newFile = string.Concat(fName, dateStamp);
File.Move(fName,newFile);
}
public void OnCreated(object sender, FileSystemEventArgs e)
{
FileInfo file = new FileInfo(e.Name);
string dateStamp = DateTime.Now.ToString("fff");
string fName = file.Name;
string newFile = string.Concat(fName, dateStamp);
File.Move(fName, newFile);
}
private void BrowseButton_Click(object sender, EventArgs e)
{
// Create FolderBrowserDialog object.
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
// Show a button to create a new folder.
folderBrowserDialog.ShowNewFolderButton = true;
DialogResult dialogResult = folderBrowserDialog.ShowDialog();
// Get selected path from FolderBrowserDialog control.
if (dialogResult == DialogResult.OK)
{
FilePathField.Text = folderBrowserDialog.SelectedPath;
Environment.SpecialFolder root = folderBrowserDialog.RootFolder;
}
}
Whenever I create a new file in the folder I'm watching, it does absolutely nothing. At first I thought it may be because I only had the "OnCreated" method, so I then copied it into the "OnChanged" method (I wasn't sure if copying an existing file into the folder counted as it being "created" but I've had no luck).
Out of interest, I'm also getting an exception thrown if I don't specify a type in the filter, but that's much less pressing at the minute.
If anyone can offer any pointers of where I may be going wrong, it'd be greatly appreciated.
There are a few problems with your code.
First, you should use e.FullPath instead of e.Name, otherwise the code will try to rename the file in the current directory, instead of watched directory.
Second, to receive Created event you should include NotifyFilters.FileName.
However, this will not help you much, because the file is locked in the created and changed events until the file is copied, so you'll get an exception. Also, you'll probably receive more than one Changed event (in my tests I always receive two, regardless of the file size, but it may be different on the different versions of Windows or .Net framework).
To fix this, you may use timers or threads to accomplish the task. Here's an example using ThreadPool thread. Whenever created is fired, you create a new thread. In the thread you check whether a file is locked (trying to open file), and when the file is unlocked, do the rename.
public class FileMon
{
public static void Run()
{
FileSystemWatcher fsWatcher = new FileSystemWatcher();
fsWatcher.Path = #"C:\Test\";
fsWatcher.Filter = "*.*" ;
fsWatcher.IncludeSubdirectories = true;
// Monitor all changes specified in the NotifyFilters.
fsWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName ;
fsWatcher.EnableRaisingEvents = true;
// Raise Event handlers.
fsWatcher.Changed += OnChanged;
fsWatcher.Created += OnCreated;
Console.WriteLine("[Enter] to end"); Console.ReadLine();
fsWatcher.EnableRaisingEvents = false;
}
static void Worker(object state)
{
FileSystemEventArgs fsArgs = state as FileSystemEventArgs;
bool done = false;
FileInfo fi = new FileInfo(fsArgs.FullPath);
do
{
try
{
using (File.Open(fsArgs.FullPath, FileMode.Open))
{
done = true;
}
}
catch
{
done = false;
}
Thread.Sleep(1000);
} while (!done);
Console.WriteLine("DOne");
string dateStamp = DateTime.Now.ToString("fff");
string fName = fi.FullName;
string newFile = fsArgs.FullPath + dateStamp;
File.Move(fsArgs.FullPath, newFile);
}
private static void OnCreated(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"Created {e.ChangeType} : {e.Name}");
ThreadPool.QueueUserWorkItem(Worker, e);
}
static void OnChanged(object sender, FileSystemEventArgs e)
{
Console.WriteLine($"{e.ChangeType} : {e.FullPath}");
}
}

c# FileSystemWatcher trigger delete event when i create a new New Microsoft Excel Worksheet.xlsx file

C# FileSystemWatcher trigger delete event when i create new "New Microsoft Excel Worksheet.xlsx" file.
Step 1: I create new file "New Microsoft Excel Worksheet.xlsx"
Step 2: The FileSystemWatcher trigger Create event
Step 3: The FileSystemWatcher trigger Delete event
I don't want to have any delete events when I create an excel file.
This is my code:
class Program
{
static void Main(string[] args)
{
var monitorSyncing = new MonitorSyncing(ConfigurationManager.AppSettings["MONITORING_FOLDER_PATH"]);
monitorSyncing.Monitoring();
Console.ReadLine();
}
}
public class MonitorSyncing
{
public MonitorSyncing(string monitorPath)
{
this._monitorPath = monitorPath;
}
private readonly string _monitorPath;
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public void Monitoring()
{
Console.WriteLine($"*** START MONITOR FOLDER: {this._monitorPath} ***");
var fileSystemWatcherSyncFolderUserSettings = new FileSystemSafeWatcher
{
Path = _monitorPath,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.Size | NotifyFilters.FileName | NotifyFilters.DirectoryName | NotifyFilters.Security,
InternalBufferSize = 24576,
};
fileSystemWatcherSyncFolderUserSettings.Changed += OnChanged_SyncFolderUserSetting;
fileSystemWatcherSyncFolderUserSettings.Created += OnChanged_SyncFolderUserSetting;
fileSystemWatcherSyncFolderUserSettings.Deleted += OnChanged_SyncFolderUserSetting;
fileSystemWatcherSyncFolderUserSettings.Renamed += OnRenamed_SyncFolderUserSetting;
fileSystemWatcherSyncFolderUserSettings.Error += OnError;
fileSystemWatcherSyncFolderUserSettings.IncludeSubdirectories = true;
fileSystemWatcherSyncFolderUserSettings.EnableRaisingEvents = true;
}
private static void OnChanged_SyncFolderUserSetting(object source, FileSystemEventArgs e)
{
switch (e.ChangeType)
{
case WatcherChangeTypes.Created:
Console.WriteLine($"{DateTime.Now:dd-MM-yyyy HH:mm:ss.fff}. Created file: {e.FullPath}");
break;
case WatcherChangeTypes.Deleted:
Console.WriteLine($"{DateTime.Now:dd-MM-yyyy HH:mm:ss.fff}. Deleted file: {e.FullPath}");
break;
case WatcherChangeTypes.Changed:
Console.WriteLine($"{DateTime.Now:dd-MM-yyyy HH:mm:ss.fff}. Edit content file: {e.FullPath}");
break;
}
}
private static void OnRenamed_SyncFolderUserSetting(object source, RenamedEventArgs e)
{
// Show that a file has been renamed.
Console.WriteLine($"{DateTime.Now:dd-MM-yyyy HH:mm:ss.fff}. Renamed file '{e.OldFullPath}' to '{e.FullPath}'");
}
private static void OnError(object source, ErrorEventArgs e)
{
// Show that an error has been detected.
Console.WriteLine($"Error - The FileSystemWatcher has detected an error : {e.GetException().Message}");
// Give more information if the error is due to an internal buffer overflow.
if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
{
Console.WriteLine(("Error - The file system watcher experienced an internal buffer overflow: " + e.GetException().Message));
}
}
}

FileSystemWatcher: multiple type

I want to send a file which has been found when the System Watcher has discoverd a created file ending with ".txt", ".doc" or ".docx". My Problem is that the System Watcher discover just files ending with ".txt".
Here is my Code:
private String Attachmenttosend
{
get { return attachmentfile; }
set { attachmentfile = value; }
}
private void NewFileSystemWatcher()
{
String filter = "*.txt,*.doc,*.docx";
string[] FileExtension = filter.Split(',');
for (int i = 0; i < FileExtension.GetLength(0); i++)
{
watcher = new FileSystemWatcher(folder); // on its own Thread
watcher.Created += new FileSystemEventHandler(NewEMail);
attachmenttosend.Add(Attachmenttosend);
watcher.Filter = FileExtension[i];
watcher.EnableRaisingEvents = true;
watchlist.Add(watcher);
}
Send(Attachmenttosend);
}
private void NewEMail(Object source, FileSystemEventArgs e)
{
while (Locked(e.FullPath)) // check if the file is used
{
Thread.Sleep(10);
}
Attachmenttosend = e.FullPath; // store the filename
}
I think this will help you,just create a console app on the fly and paste this in and try it out:
private static string[] filters = new string[] { ".txt", ".doc", ".docx" };
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"C:\...\...\...";//your directory here
/* 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;
//dont set this
//watcher.Filter = "*.txt";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.Created += new FileSystemEventHandler(OnChanged);
watcher.Deleted += new FileSystemEventHandler(OnChanged);
watcher.Renamed += new RenamedEventHandler(OnRenamed);
watcher.EnableRaisingEvents = true;
Console.ReadKey();
}
private static void OnChanged(object source, FileSystemEventArgs e)
{
if(filters.Contains(Path.GetExtension(e.FullPath)))
{
Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
//Attachmenttosend = e.FullPath;
}
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
if (filters.Contains(Path.GetExtension(e.FullPath)))
Console.WriteLine("File: {0} renamed to {1}", e.OldFullPath, e.FullPath);
}
Also as Kunal pointed out
attachmenttosend.Add(Attachmenttosend);
I guess from the uppercase and lower case that you are trying to add to the backing field of the property its own property,dont,also...you dont add to a string only += (concat).
Unless attachmenttosend is a for example a list of strings.

Categories