Reputation: 19
I am using a FileSystemWatcher class and I need it to monitor my plugged flash drives for any created or pasted files from anywhere. I refresh my list of plugged drives every 2 seconds (in case of any new plugged arrived drives), then setting FileSystemWatcher.EnableRaisingEvents = true, then after 2 seconds I set it to "false", then again refresh plugged drives list etc.
When the refreshing interval is 2 sec, the situation is the following:
BUT! When the refreshing interval is 30 sec, the situation is the following:
It is obvious that the problem hosts in the fact, that the FileSystemWatcher is not cleared itself properly and that "not-happened-events" are somehow accumulating in it, then they appear all together when the "Created" event really occurs.
It is necessary to keep refreshing interval low (about 2-3-5 sec). I cannot raise it to several minutes.
Please help. I am stuck with it for six hours. Thanks. Sorry for my English, it's not native.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Management;
using System.Diagnostics;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Threading;
private static FileSystemWatcher watcher1 = new FileSystemWatcher();
private static DriveInfo[] GetDrivesList()
{
DriveInfo[] DriveList = DriveInfo.GetDrives();
return DriveList;
}
static bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
if (is_directory == false)
{
try
{
stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
}
return false;
}
static void OnChanged(Object source, FileSystemEventArgs e)
{
FileInfo fileInfo = new FileInfo(e.FullPath);
FileInfo fileInfo2 = new FileInfo(@"D:\Shadow Copies.log");
if (Convert.ToString(e.ChangeType) == "Created")
{
Console.WriteLine("File: {0} has been {1}", e.FullPath, e.ChangeType);
file_copied = false;
int length = Convert.ToString(e.FullPath).Length;
String Path = "";
String FileName = "";
for (int i = length - 1; i >= 0; i--)
{
if (Convert.ToString(e.FullPath)[i] != '\\')
{
Path += Convert.ToString(e.FullPath)[i];
}
else
{
break;
}
}
for (int i = Path.Length - 1; i >= 0; i--)
{
FileName += Path[i];
}
for (int i = FileName.Length - 1; i >= 0; i--)
{
if (FileName[i] == '.')
{
is_directory = false;
break;
}
}
string path = Convert.ToString(e.FullPath);
while (IsFileLocked(fileInfo) == true)
{
Thread.Sleep(100);
Console.WriteLine("Retrying in 1 sec...");
}
ProcessStartInfo psi = new ProcessStartInfo();
psi.CreateNoWindow = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.FileName = "cmd.exe";
psi.Arguments = @"/c xcopy " + path + @" D:\ShadowCopies\ /s /y";
Process proc = Process.Start(psi);
file_copied = true;
Console.WriteLine("File: {0} has been Copied", e.FullPath);
DateTime datetime = DateTime.Now;
CandidateLine = e.FullPath;
write_to_log = String.Format("{0} File: {1} has been Copied\r\n", datetime.ToString(), e.FullPath);
if (CandidateLine == LastLineWritten)
return;
while (IsFileLocked(fileInfo2) == true)
{
Thread.Sleep(100);
Console.WriteLine("Retrying...");
}
File.AppendAllText(@"D:\Shadow Copies.log", write_to_log);
LastLineWritten = CandidateLine;
is_directory = true;
ProcessStartInfo psi2 = new ProcessStartInfo();
psi2.CreateNoWindow = true;
psi2.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi2.FileName = "cmd.exe";
psi2.Arguments = "/c for /d %F in (D:\\ShadowCopies\\*) do rd /s /q %F";
Process proc2 = Process.Start(psi2);
}
}
private static void WatchersInitialize()
{
DriveInfo[] DriveList = GetDrivesList();
string[] DriveListArray = new string[DriveList.Length - 1];
for (int i = 0; i < DriveListArray.Length; i++)
{
DriveListArray[i] = DriveList[i + 1].Name;
}
watcher1.IncludeSubdirectories = true;
watcher1.Path = DriveListArray[drive_position];
watcher1.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime |
NotifyFilters.DirectoryName | NotifyFilters.FileName |
NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size;
watcher1.Changed += new FileSystemEventHandler(OnChanged);
watcher1.Created += new FileSystemEventHandler(OnChanged);
watcher1.EnableRaisingEvents = true;
return 0;
}
static void Main(string[] args)
{
while (true)
{
watcher1.EnableRaisingEvents = false;
watcher2.EnableRaisingEvents = false;
watcher3.EnableRaisingEvents = false;
watcher4.EnableRaisingEvents = false;
watcher5.EnableRaisingEvents = false;
WatchersInitialize();
Thread.Sleep(2000);
}
}
Upvotes: 0
Views: 304
Reputation: 4893
You should be initializing the watcher once and subscribe to event handler once, instead you have your initialization of the same watcher in an infinite loop with 2 sec sleep. In your initialization block you keep adding the even handler for changed and created event. As these are the same physical instance of watcher, you are just accumulating event handler callbacks one after another as you loop through your infinite loop.
This is most likely the reason your events are firing hundreds of time as you subscribing more and more to the same event in every iteration.
You need to take the call WatchersInitialize();
outside of your while loop.
Upvotes: 0
Reputation: 3316
Where you attach the event handlers I think you should remove them first to be sure you aren't doubling up on the events being fired.
watcher1.Changed -= new FileSystemEventHandler(OnChanged);
watcher1.Created -= new FileSystemEventHandler(OnChanged);
watcher1.Changed += new FileSystemEventHandler(OnChanged);
watcher1.Created += new FileSystemEventHandler(OnChanged);
Upvotes: 0