开发者

Filesystem Watcher in C#

开发者 https://www.devze.com 2023-03-20 05:20 出处:网络
Currently I have a Windows Service which constantly monitors 4 folders. I have used FileSystemWatchers to monitor folders.

Currently I have a Windows Service which constantly monitors 4 folders. I have used FileSystemWatchers to monitor folders.

But everytime a new folder is added, I have to uninstall the 开发者_Go百科service add a new filesystemwatcher and then install the service.

I am thinking to make it dynamic or db driven where I dont not have to uninstall and re-install the service every time the program needs to monitor a new folder.

How can I achieve this?

Thanks in advance.


You could use an XML configuration file that the application periodically reads and caches for new folders. These would go in the app.settings file.

<configuration>
    <appSettings>
        <add key = "FolderToWatch" value = "C:\SomeFolder\" />
        <add key = "FolderToWatch" value = "C:\SomeFolder\AnotherOne\" />
        <add key = "FolderToWatch" value = "D:\LastOne\" />
    </appSettings>
</configuration>


Use a config file to add your new locations. Then all you should have to do is restart the service any time you add a new location to your config file.


Here you have a demo that uses XML with Linq2XML and has the check over the config file change:

class Program
{
    static List<FileSystemWatcher> _watchers = new List<FileSystemWatcher>();
    static bool _shouldReload = false;

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

    static void Main(string[] args)
    {
        var configWatcher = new FileSystemWatcher(Path.GetDirectoryName(Path.GetFullPath("config.xml")), "config.xml");
        configWatcher.Changed += (o, e) =>
        {
            lock (_watchers)
            {
                _watchers.ForEach(w => { w.EnableRaisingEvents = false; w.Dispose(); });
                _watchers.Clear();
            }

            _shouldReload = true;
        };

        configWatcher.EnableRaisingEvents = true;

        Thread t = new Thread((ThreadStart)(() => {
            while (true)
            {
                Thread.Sleep(5000); // reload only every five seconds (safety measure)
                if (_shouldReload)
                {
                    _shouldReload = false;
                    Console.WriteLine("Reloading configuration.");
                    WaitReady(Path.GetFullPath("config.xml"));
                    loadConfigAndRun();
                }
            }
        }));

        t.IsBackground = true;
        t.Start();

        loadConfigAndRun();

        Console.ReadLine();
    }

    static void loadConfigAndRun()
    {
        var config = XElement.Load("config.xml").Elements();
        var paths = from watcher in config select watcher.Attribute("Folder").Value;

        foreach (var path in paths)
        {
            var watcher = new FileSystemWatcher(path);
            watcher.Created += new FileSystemEventHandler(watcher_Changed);
            watcher.Changed += new FileSystemEventHandler(watcher_Changed);
            watcher.Deleted += new FileSystemEventHandler(watcher_Changed);
            watcher.Renamed += new RenamedEventHandler(watcher_Renamed);
            watcher.EnableRaisingEvents = true;
            _watchers.Add(watcher);
        }
    }

    static void toggleWatcher(string path)
    {
        var watcher = _watchers.FirstOrDefault(w => w.Path == path);

        if (watcher != null)
        {
            watcher.EnableRaisingEvents = !watcher.EnableRaisingEvents;
        }
    }

    static void watcher_Renamed(object sender, RenamedEventArgs e)
    {
        var watcher = sender as FileSystemWatcher;

        Console.WriteLine("Something renamed in " + watcher.Path);
    }

    static void watcher_Changed(object sender, FileSystemEventArgs e)
    {
        var watcher = sender as FileSystemWatcher;

        Console.WriteLine("Something changed in " + watcher.Path);
    }
}

This is the config.xml:

<?xml version="1.0" encoding="utf-8" ?>
<Watchers>
  <Watcher Folder="d:\ktm"></Watcher>
  <Watcher Folder="c:\windows"></Watcher>
</Watchers>


I would use an .xml file as @Yuck suggested, however, I would just watch the .xml file. Load the .xml when the services starts and monitor the .xml file thereafter for changes; if the .xml file LastWriteTime changes, reload it.

0

精彩评论

暂无评论...
验证码 换一张
取 消