Introduction
Note: now Smartwatcher is hosted by CodePlex , you can download the code and check updates on
https://smartwatcher.codeplex.com/
Smart Watcher is a simple windows service designed to watch a specific directories and taking specific actions to : Create - Change - Rename - Delete files events into those directories.
The advantage of this tool:
- Supporting plugins, just code about you business (what you want to do with file) compile your code into dll and let Smart Watcher take care about files watching.
- Check if file is used by another service and wait before processing it (very useful specially when you are working with large files when coping or downloading them).
- Support multiple file extensions and filters.
- Using Regular Expressions for files filtering. - Watch many directories at the same time.
- Creating a queue if many files created at the same time.
- Archive the files into password protected zip files in case of success or failure.
Using the tool
To use Smart Watcher you just need to install the service and develop your plugins then add them to the plugin folder into service root.
To install the service just double click on the service executable file ( thank you to Sudheer Reddy Battula for his article : Installing .NET Windows Services (the easiest way) )
before starting the service you should set the SuccessArchivePath and FailureArchivePath settings into exe config file, to tell the service were you want to archive a zipped
copy of files after processing. Also the 'ReadTries' into settings determine how many time the service should try to access a file in case in it using by another service,
you should increase this value in case you are downloading large files. To create you plugin create a new class library project and inherit your class from the IPlugin interface
and handle the interface properties and methods.
string Name { get; set; }
string WatchPath { get; set; }
string Filter { get; set; }
bool CatchAllFiles { get; set; }
string ZipPassword { get; set; }
string FilePrefix { get; set; }
IPluginHost Host { get; set; }
bool ArchiveFiles { get; set; }
bool DeleteFiles { get; set; }
bool FileCreated(string fileName);
bool FileChanged(string fileName);
bool FileDeleted(string fileName);
bool FileRenamed(string fileName);
Name : the name of you plugin.
WatchPath : the path of the directory where you want the service to watch.
Filter: filter string used to determine what files are monitored in a directory.
ZipPassword : the password of the zip file created for archiving.
FilePrefix : a prefix added to the name of zipped files for archiving.
ArchiveFiles : if True Let the service to archive files by zipping and saving them into specific folders.
DeleteFiles : if True delete the file after finishing.
compile your library after that take the assembly file and change its extension from 'dll' to '.plug'
copy the assembly to the 'Plugin' folder into Smart Watcher bin folder
finally start the service.
Deeper Look
By installing the service and writing your plugins you just scratch the surface, Let 's take deeper look about
how Smart Watcher is working, first of all let me redefine Smart Watcher for you with another words :
Smart Watch is a windows service which encapsulate FileSystemWatcher class, it is plug able service so you
can write your plugins and each plugin could be associated to watch a specific folder with specific file filter.
with every plugin you add, Smart Watcher automatically will create an FileSystemWatcher instance and add it to the service watchers list, The service will responsible about every thing else , it is include build in queue system to avoid any problem happen when many files created or changed at the same time, also it will check if file available and not used by another application before sending it to the appropriate plugin.
Variables
#region Variables
public static string SettingsFailureArchivePath = Properties.Settings.Default.FailureArchivePath;
public static string SettingsSuccessArchivePath = Properties.Settings.Default.SuccessArchivePath;
public static int SettingsReadTries = Properties.Settings.Default.ReadTries;
public static string SettingsZipFileExtention = "zip";
private readonly string _PluginFolder = AppDomain.CurrentDomain.BaseDirectory + @"Plugin\";
public static IPlugin[] ipi;
private List<FileSystemWatcher> _lstWatchers = new List<FileSystemWatcher>();
static FileProcessor processor;
#endregion
Methods:
#region Methods
private void LoadPlugIns()
private void RegisterWatchers()
#endregion
Constructor
In the service constructor we first create a new instance of FileProcessor class to maintain files queue, then we call LoadPlugin method to check available plugins then we call RegisterWatchers function to create watchers list.
Note: the line System.Diagnostics.Debugger.Launch(); is to debug the service, for more details please check this URL
public SmartWatcherService()
{
InitializeComponent();
#if DEBUG
System.Diagnostics.Debugger.Launch();
#endif
processor = new FileProcessor();
LoadPlugIns();
RegisterWatchers();
}
Events:
There is four main file events into the service:
- fswWatcher_Changed : Event occurs when the contents of a File or Directory are changed
- fswWatcher_Created : Event occurs when the a File or Directory is created
- fswWatcher_Deleted : Event occurs when the a File or Directory is deleted
- fswWatcher_Renamed : Event occurs when the a File or Directory is renamed.
Each one of these events when fired calls the function processor.QueueInput(e.FullPath, e.ChangeType);
where
"e.FullPath" is the file name and e.ChangeType is the type of event , the QueueInput function add the file to a queue and it wait its turn for processing,
when the file is ready two important functions are called .
private void ProcessFile(string fileInfo)
{
string[] file = fileInfo.Split('|');
WatcherChangeTypes changeType;
WatcherChangeTypes.TryParse(file[0], true, out changeType);
string filepath = file[1];
if (!File.Exists(filepath))
{
return;
}
if (!WaitReady(filepath, SmartWatcherService.SettingsReadTries))
{
return;
}
foreach (IPlugin t in SmartWatcherService.ipi)
{
string strFiletr = t.Filter.Replace("*", @"\\*");
Match match = Regex.Match(Path.GetFileName(filepath), strFiletr);
if (match.Success == true)
{
Func<string, bool> pluginFunc = null;
switch (changeType)
{
case WatcherChangeTypes.Created:
{
pluginFunc = t.FileCreated;
break;
}
case WatcherChangeTypes.Changed:
{
pluginFunc = t.FileChanged;
break;
}
case WatcherChangeTypes.Renamed:
{
pluginFunc = t.FileRenamed;
break;
}
case WatcherChangeTypes.Deleted:
{
pluginFunc = t.FileDeleted;
break;
}
}
ProcessPluginAction(pluginFunc, filepath, t.ArchiveFiles, t.DeleteFiles, t.FilePrefix,
t.ZipPassword);
}
}
}
the ProcessFile function look for which plugin has filter apply with this file using Regex which (so more than one plugin can process the file if the filter is apply) and for each apply it call the "ProcessPluginAction" function.
private void ProcessPluginAction(Func<string, bool> pluginMethod, string fileFullName, bool archiveFiles, bool deleteFiles, string filePrefix, string zipPassword)
{
string strArchivePath = SmartWatcherService.SettingsFailureArchivePath;
try
{
pluginMethod(fileFullName);
strArchivePath = SmartWatcherService.SettingsSuccessArchivePath;
}
catch (Exception ex)
{
}
finally
{
if (archiveFiles == true)
{
string strArchiveFileName = filePrefix + "_" + DateTime.Now.ToString("yyyyMMddHHmmssss") + "_" +
Path.GetFileName(fileFullName) + "." + SmartWatcherService.SettingsZipFileExtention;
ZipUtil.ZipFile(fileFullName, strArchivePath + strArchiveFileName, zipPassword);
}
if (deleteFiles == true)
{
if (File.Exists(fileFullName))
{
if (FileProcessor.WaitReady(fileFullName, SmartWatcherService.SettingsReadTries) == true)
{
File.Delete(fileFullName);
}
}
}
}
}
The ProcessPluginAction function accept delegate Func parameter represent the method should be called from the plugin and the file name will pass to this method , also the other parameters work like flags for archiving (zipping) files or delete them after finish.
Points of Interest
Smart Watcher is an easy to use tool help you to automate a lot of tasks, it is able to be extended by developing many plugins to do various kinds of actions like : sending mails, printing documents, transferring files , Start programs , ..
I can compare it to some commercial solutions like :WatchDirectory
For files zipping I am using the open source library : SharpZipLib
History
2013/1/13 Initial Release 0.1
2013/08/06 Project added to CodePlex as SmartWatcher
2013/09/05 SmartWatcher 1.3.0.0 has been released, You can check release notes and get its source code from here: SmartWatcher 1.3.0.0
Release Notes:
- Add: Introducing SmartTimer: a feature which implements a timer that raises an event at user-defined intervals. Now SmartWatcher support the Tick event
which regularly invokes code. Every several seconds or minutes, Just handle this event in your plugin and SmartWatcher will invoke your code.
- Add: Introducing SmartActions: a library will include code snippets and function so you can use them directly into SmartWatcher plugins.
- Add: PluginsLibrary folder to SmartWatcher project to add future plugins.