renat2
renat2

Reputation: 19

c# FileSystemWatcher - Raising hundreds of unwanted excessive events every several seconds

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:

  1. The program works for 1 second and I paste the file to the flash drive - FSW raises ONE "Created" event.
  2. The program works for 3 seconds and I paste the file to the flash drive - FSW raises TWO "Created" events.
  3. The program works for 5 seconds and I paste the file to the flash drive - FSW raises THREE "Created" events.
  4. The program works for a couple of minutes and I paste the file to the flash drive - FSW raises A HUNDRED (approximately) "Created" events.

BUT! When the refreshing interval is 30 sec, the situation is the following:

  1. The program works for 1 second and I paste the file to the flash drive - FSW raises ONE "Created" event.
  2. The program works for 3 seconds and I paste the file to the flash drive - FSW raises ONE "Created" event.
  3. The program works for 40 seconds and I paste the file to the flash drive - FSW raises TWO "Created" events.

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

Answers (2)

loopedcode
loopedcode

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

Paul
Paul

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

Related Questions