Filesystemwatcher does not raise rename event handler in C# on Windows7 - c#

I am using C# 3.5 on Windows 7. We have implemented a program with a FileSystemWatcher. Here, rename event is not raised. But it is working on a few systems.
What could be causing this?

There may be a timing window in your code such that not all filesystem events are properly captured on all your systems. Can you post it?
It is a 'feature' of the underlying Win32 API ReadDirectoryChangesW and hence FileSystemWatcher that under heavy load, events can get missed. There are mitigation suggestions in the MSDN docs.

Make sure that you set your watcher:
fileSystemWatcher.EnableRaisingEvents = true;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Security.AccessControl;
using System.Security.Permissions;
using System.Text;
using System.Windows.Forms;
namespace Watcher
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
FileRenamed();
}
private static string _osLanguage = null;
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
private void FileRenamed()
{
MessageBox.Show("Code is Started Now");
// Create a new FileSystemWatcher and set its properties.
FileSystemWatcher watcher = new FileSystemWatcher();
SetDirectoryAccess(#"c:\temp");
watcher.Path = #"C:\Temp";
/* 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);
watcher.Error += new ErrorEventHandler(OnError);
// 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.
//Console.WriteLine("File: " + e.FullPath + " " + e.ChangeType);
MessageBox.Show("Something is changed in the File");
}
private static void OnRenamed(object source, RenamedEventArgs e)
{
// Specify what is done when a file is renamed.
MessageBox.Show("File Is Renamed");
//WatcherChangeTypes wct = e.ChangeType;
//Console.WriteLine("File {0} {2} to {1}", e.OldFullPath, e.FullPath, wct.ToString());
}
// This method is called when the FileSystemWatcher detects an error.
private static void OnError(object source, ErrorEventArgs e)
{
MessageBox.Show("Error Trapped");
// Show that an error has been detected.
Console.WriteLine("The FileSystemWatcher has detected an error");
// Give more information if the error is due to an internal buffer overflow.
if (e.GetException().GetType() == typeof(InternalBufferOverflowException))
{
// This can happen if Windows is reporting many file system events quickly
// and internal buffer of the FileSystemWatcher is not large enough to handle this
// rate of events. The InternalBufferOverflowException error informs the application
// that some of the file system events are being lost.
Console.WriteLine(("The file system watcher experienced an internal buffer overflow: " + e.GetException().Message));
}
}
private void button1_Click(object sender, EventArgs e)
{
//File.Move(#"\\NAS\dossier_echange\Carl\temp\Test.txt", #"\\NAS\dossier_echange\Carl\temp\Test007.txt");
File.Move(#"c:\temp\Test.txt", #"c:\temp\Test007.txt");
}
internal static void SetDirectoryAccess(string directoryPathString)
{
string everyoneString;
if (OSLanguage.Equals("en-US"))
everyoneString = "Everyone";
else
everyoneString = "Tout le monde";
//sets the directory access permissions for everyone
DirectorySecurity fileSecurity = Directory.GetAccessControl(directoryPathString);
//creates the access rule for directory
fileSecurity.ResetAccessRule(new FileSystemAccessRule(everyoneString, FileSystemRights.FullControl, AccessControlType.Allow));
//sets the access rules for directory
Directory.SetAccessControl(directoryPathString, fileSecurity);
}
public static string OSLanguage
{
get
{
if (_osLanguage == null)
_osLanguage = CultureInfo.CurrentCulture.Name;
return _osLanguage;
}
set
{
_osLanguage = value;
}
}
}
}

Related

Error when I trying to move a file in c# to an other folder with a listener on the first folder

Hello I have an error with file.Move a file to an other file with a listener to this specific folder,
I want move the file in Archive folder when a new file incomming on the folder Pending.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Permissions;
using System.Text;
using System.Threading.Tasks;
namespace ListenApp
{
class Program
{
public static class Globals
{
public static string args = "//lux.pbk/Profiles/LUX/BI14H/ProfilADW7/Desktop/trade/Pending/";
public static string archivePath = "//lux.pbk/Profiles/LUX/BI14H/ProfilADW7/Desktop/trade/archive/";
}
public static void Main()
{
Run();
}
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
private static void Run()
{
/* // 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.
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
watcher.Path = Globals.args;
// 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.Created += OnChanged;
// 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}");
Console.WriteLine(e.Name);
if(File.Exists(Globals.args + e.Name))
{
File.Move(Globals.args + e.Name, Globals.archivePath + e.Name); // System.IO.IOException: 'The process cannot access the file because it is being used by another process.'
}
}
}
}
On File.Move, I have a error, that said :
System.IO.IOException: 'The process cannot access the file because it
is being used by another process.'
How fix this?

FileSystemWatcher Not recognizing change in directory

So I am trying to create a console application that will watch a directory and when a folder is dropped into the directory it will optimize the files inside of the folder. The optimization part is working. I am currently concerned with the fact that once I run the program with the FileSystemWatcher it never recognizes the change. Is the class only focusing on the root directory and not going any deeper?
I also saw on Microsoft's website that the way to watch for a file that has been copy pasted or moved into the directory is by using FileSystemWatcher.Renamed instead of .Changed which is what I was having an issue with before.
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Mime;
using System.Runtime.CompilerServices;
using System.Threading;
using pdftron;
using pdftron.Common;
using pdftron.Filters;
using pdftron.SDF;
using pdftron.PDF;
using OptimizerTestCS;
namespace PDFNetSamples
{
class Class1
{
private static pdftron.PDFNetLoader pdfNetLoader = pdftron.PDFNetLoader.Instance();
public static void Optimize()
{
Thread.Sleep(1000);
PDFNet.Initialize();
string input_Path = #"C:\Users\user\Desktop\testinp\";
string output_Path = #"C:\Users\user\Desktop\output\";
string[] files = Directory.GetFiles(input_Path, "*.pdf", SearchOption.AllDirectories);
foreach (string file in files)
{
string fileName = Path.GetFileName(file);
Console.WriteLine($"Optimizing {fileName}");
string sub = file.Substring(35, 7);
CreateFolder(output_Path + sub);
try
{
using (PDFDoc doc = new PDFDoc(file))
{
doc.InitSecurityHandler();
Optimizer.Optimize(doc);
doc.Save(output_Path + sub + fileName, SDFDoc.SaveOptions.e_linearized);
Console.WriteLine("Done..\n");
}
}
catch (PDFNetException e)
{
Console.WriteLine(e.Message);
}
}
}
private static void Run()
{
string[] args = Environment.GetCommandLineArgs();
if (args.Length != 2)
{
Thread.Sleep(3000);
Console.WriteLine("Usage: Watcher.exe (directory)");
return;
}
using (FileSystemWatcher watcher = new FileSystemWatcher())
{
watcher.Path = #"C:\Users\user\Desktop\testinp\";
watcher.NotifyFilter = NotifyFilters.LastAccess
| NotifyFilters.LastWrite
| NotifyFilters.FileName
| NotifyFilters.DirectoryName;
watcher.Filter = "*.pdf";
watcher.Renamed += OnChanged;
watcher.EnableRaisingEvents = true;
Console.WriteLine("Press 'q' to quit the sample.");
while (Console.Read() != 'q') ;
}
}
private static void OnChanged(object source, FileSystemEventArgs e) =>
Optimize();
static void CreateFolder(string path)
{
Directory.CreateDirectory(path);
}
public static void Main(string[] args)
{
while (true)
{
Run();
}
}
}
}
Add watcher.IncludeSubdirectories = true; to include sub directories.
You need to set the IncludeSubdirectories property to true.
Like others already said, you need to add watcher.IncludeSubdirectories = true;.
I guess your Optimize Method is not working cause of the input_path, which should be different for sub-directories as it's no longer input_path + filename.
So that said, you need to adjust your input_path to match the directory which you are tracking at the moment.

Is there a way to detect if a process is encrypting or deleting a file in C#?

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);
}
}

C# Console Application - Inactivity in a folder

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.

exception rise with FileSystemWatcher

I wrote small app for monitoring file for changes.
When I run it, every time I get exception about Path. And I can't understand why. The path is really exist.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Run();
}
public static void Run()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = #"D:\test\1.txt";
watcher.NotifyFilter = NotifyFilters.LastWrite;
watcher.Changed +=new FileSystemEventHandler(watcher_Changed);
watcher.EnableRaisingEvents = true;
}
static void watcher_Changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine(e.ChangeType);
}
}
}
FileSystemWatcher.Path should be a Path not a file name
watcher.Path = #"D:\test";
watcher.Filter = "1.txt";
private static void watcher_Changed(object source, FileSystemEventArgs e)
{
// this test is unnecessary if you plan to monitor only this file and
// have used the proper constructor or the filter property
if(e.Name == "1.txt")
{
WatcherChangeTypes wct = e.ChangeType;
Console.WriteLine("File {0} {1}", e.FullPath, wct.ToString());
}
}
You can also limit the monitoring using the constructor that takes two parameters, the path and a file filter.
FileSystemWatcher watcher = new FileSystemWatcher(#"d:\test", "1.txt");
See MSDN References

Categories