I have a PHP website on a Linux server. I made a button next to the phone numbers on the site that writes a text file on the server with that number. The following code works.
$file = './gebruikers/'.$naam.'/nummer.txt';
$write = $_POST['num'];
file_put_contents($file, $write);
Now I made a C# application with TAPI3 to call the number in that text file.
I use a FileSystemWatcher (watcher) to check the folder where php saves the text file so it makes the call everytime the file gets updated.
The following code checks which user is selected so it watches the folder of that user for the text file.
private void cbGebruikers_SelectedIndexChanged(object sender, EventArgs e)
{
if(cbGebruikers.Text != "")
{
comboBox1.Enabled = true;
button6.Enabled = true;
lblGebruiker.Visible = false;
lblTelefoon.Visible = true;
}
path = #"\\192.168.1.9\SB Alarm programma\web-sb\gebruikers\" + cbGebruikers.Text;
watcher.Path = path;
watcher.NotifyFilter = NotifyFilters.LastAccess;
watcher.Filter = "*.*";
watcher.Changed += new FileSystemEventHandler(OnChanged);
watcher.EnableRaisingEvents = true;
lbltest.Text = watcher.Path.ToString();
}
When the text file changes the following code will execute.
private void OnChanged(object sender, FileSystemEventArgs e)
{
try
{
watcher.EnableRaisingEvents = false;
telnummer = File.ReadAllText(path + "/nummer.txt");
nummer = "0" + telnummer;
this.Invoke((MethodInvoker)delegate
{
txtNummer.Text = nummer;
MakeCall(nummer);
});
}
finally
{
watcher.EnableRaisingEvents = true;
}
}
This code works, if I change the text file in the folder on my PC or on another PC that has access to the folder the application makes the call.
But if PHP changes the text file nothing happens, but the last modified date does update.
Someone got experiencewith this?
This looks like an issue with using FileSystemWatcher in a cross platform architecture. FileSystemWatcher works by opening up a connection to the remote server, whose responsibility is responding when changes happen to the specified file. Windows platforms use the Win32 ReadDirectoryChanges(), while Linux boxes use Inotify API. Because there is no interface between the two APIs, the Linux box has no way of responding to the FileSystemWatcher.
Relevant links
http://msdn.microsoft.com/en-us/library/aa365465.aspx
http://www.mono-project.com/docs/faq/technical/
Can you try to change NotifyFilter to NotifyFilters.LastWrite? Or if you want to monitor both, change to NotifyFilters.LastWrite | NotifyFilters.LastAccess.
Also if the file is created by PHP, you probably want to add an event handler to watcher.Created.
Related
Yes there are many similar questions but none of them address my unique situation.
There is a separate c++ process writing the file using c++ printf and fprintf.
filename i am trying to watch is info_20160525.log
My fileSystemWatcher in winform C# application gets notification when the writer process writes to the file AND I physically access the file i-e F5 the folder or have it open in textpad and click the opened file or right click the file but I never get any event notification when I dont physically interact with the file.
Also, when I shutdown the writer application I do get the notification.
Here is my code.
public bool StartUp(string fullfilepath, int linenumber)
{
if (!File.Exists(fullfilepath))
return false;
if (!LogClass.CheckPathExists(m_applicationPath))
return false;
try
{
FileInfo info = new FileInfo(fullfilepath);
m_filename = fullfilepath;
m_fileWatcher = new FileSystemWatcher(info.DirectoryName, info.Name);
m_fileWatcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.LastAccess
| NotifyFilters.LastWrite | NotifyFilters.Size ;
m_fileWatcher.Changed += m_fileWatcher_Changed;
m_fileWatcher.Error += m_fileWatcher_Error;
m_fileWatcher.Created += m_fileWatcher_Created;
m_fileWatcher.Deleted += m_fileWatcher_Deleted;
m_fileWatcher.Disposed += m_fileWatcher_Disposed;
m_fileWatcher.Renamed += m_fileWatcher_Renamed;
m_linesRead = linenumber;
m_fileWatcher.EnableRaisingEvents = true;
}
catch(Exception e)
{
LogClass.LogError(e, "Trouble accessing the file" + fullfilepath, m_applicationPath);
}
return true;
}
These are the handlers. I have breakpoints in each one of them but I never get a trigger unless ofcourse I physically interact with the file.
void m_fileWatcher_Renamed(object sender, RenamedEventArgs e)
{
string S = "";
}
void m_fileWatcher_Disposed(object sender, EventArgs e)
{
string S = "";
}
void m_fileWatcher_Deleted(object sender, FileSystemEventArgs e)
{
string S = "";
}
void m_fileWatcher_Created(object sender, FileSystemEventArgs e)
{
string S = "";
}
void m_fileWatcher_Error(object sender, ErrorEventArgs e)
{
string S = "";
}
void m_fileWatcher_Changed(object sender, FileSystemEventArgs args)
{
if (args.ChangeType == WatcherChangeTypes.Changed)
{
while (ParseFile(args.FullPath))
{
}
}
}
I bet this thread has your answer --> FileSystemWatcher changed event (for “LastWrite”) is unreliable
The FileSystemWatcher uses an update to the LastWrite attribute of a file to fire events, however, the LastWrite is not updated in real time and should not be relied upon as trigger for an event.
If you have enough time and resources on your hands then you probably want to look into File System Filters and the simpler approach of a Filter Manager and Minifilter Driver. It is driver type development, however, it is a sure file way to accomplish your objective.
It is dug down a little deeper by system policy but gives you a wide array of events to latch onto. If I was doing this for anything like pci compliance or similar tasks then I would not use the FileSystemWatcher.
Make sure you set IncludeSubdirectories to true.
https://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher(v=vs.110).aspx
I have a csv file and I would like to make some actions whenever a new row is inserted to this csv file.
is there such a listener in c#?
Thanks a lot
There is a class FileSystemWatcher to inspect the file changes.
FileSystemWatcher MSDN. in your case, you just need to filter with "*.csv".
No, there is not specifically a listener for a row being added, but there is such a thing, in .Net, as a FileSystemWatcher, which is a class that can monitor a file for changes. With it, you can react to a specific set of changes to the file that you choose, but what happens is completely up to you.
You can use the FileSystemWatcher to watch an arbitrary file for change events:
public MainWindow()
{
InitializeComponent();
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Filter = "test1.csv";
fsw.NotifyFilter = NotifyFilters.LastWrite;
fsw.Path = "z:\\temp\\";
fsw.Changed += Fsw_Changed;
fsw.EnableRaisingEvents = true;
}
private void Fsw_Changed(object sender, FileSystemEventArgs e)
{
MessageBox.Show(e.FullPath);
}
I'm going to start off by apologizing if this is a duplicated question. There were a ton of FileSystemWatcher questions but I didn't see any that addressed my issue.
Ok, so I have a console application in C# that is monitoring a directory, which we will call Root. Root has many subfolders. The purpose of this application is to write to a log file if any .csv files are create, modified, or deleted within Root or any of its subfolders. I currently have this working fine, sort of. The only problem is that when a .csv file is created, modified, or deleted it actually raises the event for all 3.
For example, if I create a file in Root called test.csv, the log file would look like this:
10/04/2012: File F:/Root/test.csv Created
10/04/2012: File F:/Root/test.csv Changed
10/04/2012: File F:/Root/test.csv Created
10/04/2012: File F:/Root/test.csv Deleted
I'm not sure whats going on, so here is the code that sets up the FileSystemWatcher
_watchFolder.Path = ConfigurationManager.AppSettings["RootToWatch"];
_watchFolder.Filter = ConfigurationManager.AppSettings["FileNameToWatch"];
_watchFolder.NotifyFilter = NotifyFilters.FileName
| NotifyFilters.LastWrite;
_watchFolder.IncludeSubdirectories = true;
_watchFolder.Changed += new FileSystemEventHandler(OnChanged);
_watchFolder.Created += new FileSystemEventHandler(OnChanged);
_watchFolder.Deleted += new FileSystemEventHandler(OnChanged);
_watchFolder.Renamed += new RenamedEventHandler(OnRenamed);
try
{
_watchFolder.EnableRaisingEvents = true;
}
catch (ArgumentException ex)
{
AbortMonitoring(ex.Message);
}
And here is my OnChanged event (Renamed is same but has different argument)
protected static void OnChanged(object sender, FileSystemEventArgs e)
{
//compile message to insert into log file.
string message = "File: " + e.FullPath + " " + e.ChangeType;
UpdateLogFile(message);
}
Just add a handler only for the changed event. It should gather all change types. The other types of events like created are there if you want the event to be raised only on a particular change type.
watchFolder.IncludeSubdirectories = true;
_watchFolder.Changed += new FileSystemEventHandler(OnChanged);
We have users that rename the shortcut file on their desktop to our application. What is the best way to delete/modify the shortcut based on targetpath if the icon changes for the application? In other words, I'm having a hard time locating the file name because it keeps getting changed.
It's a nice question and I surprised that nobody answered it correctly in 10 years.
The code below iterate through all links in given folder and finds one with TargetPath pointing to the currently executing WinForms app.
Add COM reference to your project to Windows Script Host Object Model.
using IWshRuntimeLibrary;
private static void DeleteShortcuts(string path)
{
// Example for path: Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
foreach (var fileName in Directory.GetFiles(path, "*.lnk"))
{
WshShell shell = new WshShell();
IWshShortcut link = (IWshShortcut)shell.CreateShortcut(fileName);
if (link.TargetPath == Application.ExecutablePath)
{
System.IO.File.Delete(fileName);
}
}
}
Note: Application.ExecutablePath works for WinForms to get the current exe path, for Console app you should use Path.GetDirectoryName(Environment.GetCommandLineArgs()[0]). Refer to documentation for other types of projects.
You should use FileSystemWatcher class:
Listens to the file system change notifications and raises events when
a directory, or file in a directory, changes.
Infact you can exploit FileSystemWatcher.Changed, FileSystemWatcher.Created, FileSystemWatcher.Renamed , FileSystemWatcher.Deleted events to keep control on your file.
Here is an example by MSDN:
public static void Main()
{
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = "mypath";
/* 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;
// Wait for the user to quit the program.
Console.WriteLine("Press \'q\' to quit the sample.");
while(Console.Read()!='q');
}
// 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);
}
Renaming a shortcut does not modify the target path, however, the best way I know to work with shortcuts in c# is with the IwshRuntimeLibrary.
To delete a file please use System.IO.File.Delete method
To modify the file you can use System.IO.File.AppendText method
Update after comments from below :
Please use the ShellClass to create or modify shortcuts Also you will
need to get the special directory from desktop using
Environment.SpecialFolder.DesktopDirectory
A very good example showing step by step can be found here http://www.codeproject.com/Articles/146757/Add-Remove-Startup-Folder-Shortcut-to-Your-App
I'm trying to code a program which will watch a directory/disk and move deleted files/folders to recycle bin when they are deleted from network shared folder.
I have this code which is working when a file/folder is deleted but I need to cancel delete and move file to Recycle Bin. I found how to move file/folder to Recycle Bin here: How to Move files to the recycle bin
FileSystemWatcher fsw = new FileSystemWatcher();
private void frmMain_Load(object sender, EventArgs e)
{
StartWatcher("X:\\Virtuals\\");
}
private void StopWatcher()
{
if (fsw != null)
try
{
fsw.EnableRaisingEvents = false;
fsw.Dispose();
fsw = null;
}
catch { }
}
private void StartWatcher(string path)
{
StopWatcher();
FileSystemWatcher fsw = new FileSystemWatcher();
fsw.Path = Path.GetDirectoryName(path);
fsw.Filter = Path.GetFileName(path);
fsw.NotifyFilter = NotifyFilters.LastAccess |
NotifyFilters.LastWrite | NotifyFilters.FileName
| NotifyFilters.DirectoryName;
fsw.Deleted += new FileSystemEventHandler(OnDeleted);
fsw.EnableRaisingEvents = true;
}
private void OnDeleted(object source, FileSystemEventArgs e)
{ MessageBox.Show("File deleted: " + e.FullPath); }
FileSystemWatcher won't help you in your task. Proper way to do this is employ a filesystem filter driver which will intercept file deletion requests and move files to the recycle bin instead. You can create your own filter driver (requires knowledge of low-level kernel-mode development), or we offer CallbackFilter product which lets you do the job in user mode (even in .NET).
The FileSystemWatcher raises events after the file is actually deleted, modified or created, so it´s to late to do a copy after the delete event is raised. And there is no possibility to cancel an operation with the FileSystemWatcher. Possibly it can be solved by using some sort of low level APIs (but I don´t know which and how).