So, I have created a windows service, where I use a FileSystemWatcher to watch different directories. Every time changed files are detected I copy them in a different directory, so I can work with them later.
This works perfectly when I run the program as a Console Application.
When I run it as a service, I can start and stop the service properly, but it won't detect any kind of event. I have tried to debug my service and I found out that the error is coming from the fact that I don't stop the FileSystemWatcher.
For my console App, I have this code for the Watch() method:
public void Watch()
{
using (FileSystemWatcher watcher = new FileSystemWatcher($"C:\\Users\\wost\\AppData\\Roaming\\Sublime", _ext))
{
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
watcher.IncludeSubdirectories = true;
// Add event handlers.
watcher.Changed += OnChanged;
watcher.Created += OnChanged;
watcher.Deleted += OnChanged;
watcher.Renamed += 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') ;
}
}
So, I stop the program if the user presses 'q'.
For my Windows Service, I have this code for the Watch() method:
public void Watch()
{
using (FileSystemWatcher watcher = new FileSystemWatcher($"C:\\Users\\lashi\\AppData\\Roaming\\Sublime Text 3", _ext))
{
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
watcher.IncludeSubdirectories = true;
// Add event handlers.
watcher.Changed += OnChanged;
watcher.Created += OnChanged;
watcher.Deleted += OnChanged;
watcher.Renamed += OnRenamed;
// Begin watching.
watcher.EnableRaisingEvents = true;
}
}
So, here I don't stop the FileSystemWatcher at all, because as I don't have a direct interaction with the user, I don't know how to stop it. Can you please help me to find a solution to this?
These are the OnStart() and OnStop() methods:
public partial class Service1 : ServiceBase
{
Watcher w;
public Service1()
{
InitializeComponent();
}
protected override void OnStart()
{
w = new Watcher($"C:\\EMMC_CACHE\\expt1-log", $"C:\\EMMC_CACHE\\expt1-file", "lashi");
w.Watch();
}
protected override void OnStop()
{
DirectoryInfo dir = new DirectoryInfo(#"C:\Users\wost\Desktop\FILES");
int count = dir.GetFiles().Length;
// TEST
if (count == 0)
{
StreamWriter writer = new StreamWriter(#"C:\Users\wost\Desktop\Notes.txt");
writer.WriteLine("Service is stopped at: " + DateTime.Now);
writer.Close();
}
}
}
I think you need to make the watcher a field and not to dispose it prematurely. I didn't test this code but you see the relevant changes in 'Watch', i think....
internal class Watcher : IDisposable {
private FileSystemWatcher _watcher;
private string _directoryPath;
private string _ext;
internal Watcher (string directoryPath, string ext) {
_directoryPath = directoryPath;
_ext = ext;
}
~Watcher () {
Dispose();
}
public void Watch()
{
Dispose();
_watcher = new FileSystemWatcher(_directoryPath, _ext);
_watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
_watcher.IncludeSubdirectories = true;
// Add event handlers.
_watcher.Changed += OnChanged;
_watcher.Created += OnChanged;
_watcher.Deleted += OnChanged;
_watcher.Renamed += OnRenamed;
// Begin watching.
_watcher.EnableRaisingEvents = true;
}
public void Dispose() {
try {
_watcher?.Dispose();
} catch {
;
}
_watcher = null;
}
//FSW event handlers...
}
Related
My requirement
I am creating one desktop application , I need a network path file information which raname and create ,for that I use FileSystemWatcher
it's provide Created,Renamed,changes and deleted event
My problem
FileSystemWatcher rename event not firing for subdirectory network path,
I already set watcher.IncludeSubdirectories = true, but it not work for rename
public void Setup() {
var watcher = new FileSystemWatcher{
Path = "My network path",
NotifyFilter = NotifyFilters.FileName | NotifyFilters.Attributes | NotifyFilters.LastWrite | NotifyFilters.Security, Filter = "*"
};
watcher.Created += OnCreated;
watcher.Renamed += OnRenamed;
// uncomment out line below to add the error handler
watcher.Error += OnError;
watcher.IncludeSubdirectories = true;
watcher.EnableRaisingEvents = true;
}
public static void OnRenamed(object source, RenamedEventArgs e)
{
try
{
MessageBox.Show("Raname call");
}
catch (Exception Ex)
{
errorLog(Ex);
}
}
public static void OnCreated(object source, FileSystemEventArgs e)
{
try
{
MessageBox.Show("OnCreated call");
}
catch (Exception Ex)
{
errorLog(Ex);
}
}
I was wondering if there was a way to detect if a process is deleting or encrypting a file. I am trying to make an anti-ransomware application in C# so I was wondering if anyone could help.
Any suggestions?
You want to take a look at the FileSystemWatcher class.
From the MSDN page:
using System;
using System.IO;
using System.Security.Permissions;
public class Watcher
{
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
public static void Run()
{
string[] args = System.Environment.GetCommandLineArgs();
// If a directory is not specified, exit program.
if(args.Length != 2)
{
// Display the proper way to call the program.
Console.WriteLine("Usage: Watcher.exe (directory)");
return;
}
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[1];
/* 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);
}
}
FileSystemWatcher: how to rise events only for new files in directory?
I have a directory, which my service scan. And I use FileSystemWatcher:
constructor:
if(Directory.Exists(_dirPath))
{
_fileSystemWatcher = new FileSystemWatcher(_dirPath);
}
Then, I subscribes on Directory:
public void Subscribe()
{
try
{
//if (_fileSystemWatcher != null)
//{
// _fileSystemWatcher.Created -= FileSystemWatcher_Created;
// _fileSystemWatcher.Dispose();
//}
if (Directory.Exists(_dirPath))
{
_fileSystemWatcher.EnableRaisingEvents = true;
_fileSystemWatcher.Created += FileSystemWatcher_Created;
_fileSystemWatcher.Filter = "*.txt";
}
}
But, the problem is that i want to get events when new files create (or copy).
Instead, i get events from all files in this directory already exists.
How to get event only from new files?
Thank you!
By setting NotifyFilter to NotifyFilters.FileName | NotifyFilters.CreationTime | NotifyFilters.LastWrite you can watch if new files are created.
You also need to check e.ChangeType == WatcherChangeTypes.Created in the raised event after any change occurred.
static void Main(string[] args)
{
FileSystemWatcher watcher = new FileSystemWatcher();
string filePath = #"d:\watchDir";
watcher.Path = filePath;
watcher.EnableRaisingEvents = true;
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.CreationTime | NotifyFilters.LastWrite;
watcher.Filter = "*.*";
watcher.IncludeSubdirectories = true;
watcher.Created += new FileSystemEventHandler(OnFileCreated);
new System.Threading.AutoResetEvent(false).WaitOne();
}
private static void OnFileCreated(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created)
// some code
}
From experience I have noticed that the events that get raised when editing a file can wildly differ depending on the application that edits the the file.
Some applications overwrite, others append.
I found that polling every now and then and keeping a list of files that already existed on the previous poll was more reliable than trying to get the events right.
I am fairly new to C# coding.. I am trying to setup a code that will alert me when there is an inactivity in a folder. We have a current and archive folder. Once the file is processed in the current folder it will move onto the archive folder.
I have the code to check if there are files in the current folder that's the easy part
DirectoryInfo id = new DirectoryInfo(#"C\");
FileInfo[] TXTFiles = id.GetFiles("*.txt");
if (TXTFiles.Length == 0)
{
Console.WriteLine("Files does not ");
Console.WriteLine("Checking the last processed file in the Archive directory");
Console.Read();
}
if (TXTFiles.Length != 0)
{
Console.WriteLine("Files exists ");
Console.Read();
}
So in the logic where the file does not exist I want to have an additional step to get the timestamp of the last text file that was processed. This is to check for how long there hasnt been any activity .
I am not sure how to proceed. Also instead of writing this information to a console can i send a message to a webservice
Thanks
FileSystemWatcher will be your friend :)
https://msdn.microsoft.com/fr-fr/library/system.io.filesystemwatcher(v=vs.110).aspx
using System;
using System.IO;
using System.Security.Permissions;
public class Watcher
{
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name="FullTrust")]
public static void Run()
{
string[] args = System.Environment.GetCommandLineArgs();
// If a directory is not specified, exit program.
if(args.Length != 2)
{
// Display the proper way to call the program.
Console.WriteLine("Usage: Watcher.exe (directory)");
return;
}
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[1];
/* 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);
}
}
Source code from MSDN.
This question already has answers here:
FileSystemWatcher Changed event is raised twice
(44 answers)
Closed 7 years ago.
I am using the below code to practice FileSystemWatcher.Changed Event from here. It perfectly works fine with .txt extension, but the output is not as I expect to see when I use .pdf. It triggers one "Created" events and multiple "Changed" events.
using System;
using System.IO;
using System.Security.Permissions;
public class Watcher
{
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
public static void Run()
{
string[] args = System.Environment.GetCommandLineArgs();
// If a directory is not specified, exit program.
if (args.Length != 2)
{
// Display the proper way to call the program.
Console.WriteLine("Usage: Watcher.exe (directory)");
return;
}
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = args[1];
/* 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 = "*.pdf";
// 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);
}
}
Here is the output when I copy a PDF file to watching folder:
File: c:\test\innovation.pdf Created
File: c:\test\innovation.pdf Changed
File: c:\test\innovation.pdf Changed
File: c:\test\innovation.pdf Changed
File: c:\test\innovation.pdf Changed
Any idea why that happens?
Thanks to Ahmed Ilyas. All I needed to do was to change:
watcher.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite
| NotifyFilters.FileName | NotifyFilters.DirectoryName;
to
watcher.NotifyFilter = NotifyFilters.FileName;