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.
精彩评论