Oli
Oli

Reputation: 1

Filesystemwatcher randomly stopps working

I wrote a little program which I run as a Windows-Service, which moves Files of an Inbox-Folder to another location on receive. But randomly it stops working (Service still runing, process not crashing). If I just move them out the inbox and back, it starts again. Any hints to improve?

//CIPCoyService.cs


using System;
using System.Diagnostics;
using System.IO;
using System.ServiceProcess;
using System.Threading;

namespace CopyCIP
{
    public partial class CIPCopyService : ServiceBase
    {
        public CIPCopyService()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {          
            // start the triggers
            initXML();
            initPDF();
            initCSV();
        }

        private static void initXML()
        {
            FileSystemWatcher WatcherXML = new FileSystemWatcher();
            WatcherXML.Path = @"C:\xxx\baseDir\inbox";
            WatcherXML.IncludeSubdirectories = false;
            WatcherXML.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
            WatcherXML.Filter = "*.xml";
            WatcherXML.Created += new FileSystemEventHandler(Watcher_ChangedXML);
            WatcherXML.EnableRaisingEvents = true;

        }

        private static void initPDF()
        {
            FileSystemWatcher WatcherPDF = new FileSystemWatcher();
            WatcherPDF.Path = @"C:\xxx\baseDir\inbox";
            WatcherPDF.IncludeSubdirectories = false;
            WatcherPDF.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
            WatcherPDF.Filter = "*.pdf";
            WatcherPDF.Created += new FileSystemEventHandler(Watcher_ChangedPDF);
            WatcherPDF.EnableRaisingEvents = true;

        }

        private static void initCSV()
        {
            FileSystemWatcher WatcherCSV = new FileSystemWatcher();
            WatcherCSV.Path = @"C:\xxx\baseDir\inbox";
            WatcherCSV.IncludeSubdirectories = false;
            WatcherCSV.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
            WatcherCSV.Filter = "*.csv";
            WatcherCSV.Created += new FileSystemEventHandler(Watcher_ChangedCSV);
            WatcherCSV.EnableRaisingEvents = true;

        }

        private static void Watcher_ChangedXML(object sender, FileSystemEventArgs e)
        {
            //move the XML stuff
            string XMLPath = @"\\xxx\d$\CIP\Admin\Prod\SN\Import\Eingang\eSCHKG\";

            if (File.Exists(e.FullPath))

                // Ensure that the target does not exist.
                if (File.Exists(Path.Combine(XMLPath,e.Name)))
                    File.Delete(Path.Combine(XMLPath, e.Name));

                WaitReady(e.FullPath);
                try
                {

                    File.Move(e.FullPath, Path.Combine(XMLPath, e.Name));
                }
                catch (IOException ex)
                {
                    eventWriteEx(ex, "XML");
                }
        }

        private static void Watcher_ChangedPDF(object sender, FileSystemEventArgs e)
        {
            // move the PDF stuff
            string PDFPath = @"\\xxx\d$\CIP\Admin\Prod\SN\Import\Eingang\eSCHKG\PDF\";

            if (File.Exists(e.FullPath))

                // Ensure that the target does not exist.
                if (File.Exists(Path.Combine(PDFPath, e.Name)))
                    File.Delete(Path.Combine(PDFPath, e.Name));

                WaitReady(e.FullPath);
                try
                {
                    File.Move(e.FullPath, Path.Combine(PDFPath, e.Name));
                }
                catch (IOException ex)
                {
                    eventWriteEx(ex, "PDF");
                }
        }

        private static void Watcher_ChangedCSV(object sender, FileSystemEventArgs e)
        {
            // move the CSV stuff
            string CSVPath = @"\\xxx\d$\CIP\Admin\Prod\SN\Import\Eingang\eSCHKG\CSV\";

            if (File.Exists(e.FullPath))

                // Ensure that the target does not exist.
                if (File.Exists(Path.Combine(CSVPath, e.Name)))
                    File.Delete(Path.Combine(CSVPath, e.Name));

                WaitReady(e.FullPath);
                try
                {
                    WaitReady(e.FullPath);
                    File.Move(e.FullPath, Path.Combine(CSVPath, e.Name));
                }
                catch (Exception ex)
                {
                    eventWriteEx(ex, "CSV");
                }
        }

        private static void eventWriteEx(Exception ex, string what)
        {
            string eSource = "CIPCopyService";

            if (!EventLog.SourceExists(eSource))
                EventLog.CreateEventSource(eSource, "CIPEvents");

            EventLog.WriteEntry("CIPCopy Exception" + what, ex.Message + "Trace" + ex.StackTrace, EventLogEntryType.Error);
        }

        private static void eventWriteInfo(string what)
        {
            string eSource = "CIPCopyService";

            if (!EventLog.SourceExists(eSource))
                EventLog.CreateEventSource(eSource, "CIPEvents");

            EventLog.WriteEntry(eSource, what);
        }


        public static void WaitReady(string fileName)
        {
            while (true)
            {
                try
                {
                    using (Stream stream = File.Open(fileName, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
                    {
                        if (stream != null)
                        {
                            eventWriteInfo(string.Format("Output file {0} ready.", fileName));
                            break;
                        }
                    }
                }
                catch (FileNotFoundException ex)
                {
                    eventWriteEx(ex, string.Format("Output file {0} not yet ready ({1})"));
                }
                catch (IOException ex)
                {
                    eventWriteEx(ex, string.Format("Output file {0} not yet ready ({1})"));
                }
                catch (UnauthorizedAccessException ex)
                {
                    eventWriteEx(ex, string.Format("Output file {0} not yet ready ({1})"));
                }
                Thread.Sleep(500);
            }
        }

        protected override void OnStop()
        {

        }
    }
}

Upvotes: 0

Views: 109

Answers (1)

Romano Zumbé
Romano Zumbé

Reputation: 8079

FileSystemWatcher has a limitation if many files are touched in a short amount of time. The internal buffer of the FileSystemWatcher is full and any changes that occur until the buffer has free space can't get handled. You can increase the buffer to a maximum of 65536:

watcherXML.InternalBufferSize = 65536;

But even this has a limitation. If you expect really huge amounts of files you should probably use a Timer and move all existing files to the new location;

private static void initXML()
{
    Timer timer = new Timer();
    timer.Interval = 1000;
    timer.Tick += (y,z) => 
    {
        foreach(string file in Directory.GetFiles(@"C:\xxx\baseDir\inbox")
        {
            MoveFile(file);
        }
    };

    timer.Start();
}

private void MoveFile(string file)
{
    string XMLPath = @"\\xxx\d$\CIP\Admin\Prod\SN\Import\Eingang\eSCHKG\";
    string fileName = Path.GetFileName(file);
    if (File.Exists(file))
        // Ensure that the target does not exist.
        if (File.Exists(Path.Combine(XMLPath,fileName )))
            File.Delete(Path.Combine(XMLPath, fileName ));

        WaitReady(file);
        try
        {
            File.Move(file, Path.Combine(XMLPath, fileName));
        }
        catch (IOException ex)
        {
            eventWriteEx(ex, "XML");
        }
    }

Upvotes: 2

Related Questions