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. 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;}
        string WatchPath { get;}
        string Filter { get;}
        NotifyFilters NotifyFilter { get;}
        bool CatchAllFiles { get;}
        string ZipPassword { get;}
        string FilePrefix { get;}
        IPluginHost Host { get; set; }
        bool ArchiveFiles { get;}
        bool DeleteFiles { get;}

        /// <summary>
        /// Event occurs when the a File or Directory is created
        /// </summary>
        /// <param name="fileName">The file full path name</param>
        /// <returns></returns>
        bool FileCreated(string fileName);
        /// <summary>
        /// Event occurs when the contents of a File or Directory are changed
        /// </summary>
        /// <param name="fileName">The file full path name</param>
        /// <returns></returns>
        bool FileChanged(string fileName);
        /// <summary>
        /// Event occurs when the a File or Directory is deleted
        /// </summary>
        /// <param name="fileName">The file full path name</param>
        /// <returns></returns>
        bool FileDeleted(string fileName);
        /// <summary>
        /// Event occurs when the a File or Directory is renamed
        /// </summary>
        /// <param name="fileName">The file full path name</param>
        /// <returns></returns>
        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.

NotifyFilter: used to detect the type of changes to watch for.

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
// Failur archive folder path from service setting
public static string SettingsFailureArchivePath = Properties.Settings.Default.FailureArchivePath;
// Success archive folder path from service setting
public static string SettingsSuccessArchivePath = Properties.Settings.Default.SuccessArchivePath;
// How many tries to access the file in case it used by another service
public static int SettingsReadTries = Properties.Settings.Default.ReadTries;
// the extention of zipped archived files
public static string SettingsZipFileExtention = "zip";
// the path of plugin folder (where the Smart Watcher will look for its plugins)
private readonly string _PluginFolder = AppDomain.CurrentDomain.BaseDirectory + @"Plugin\";

// a list of the avilable plugins into Plugin folder
public static IPlugin[] ipi;

// List of file watchers (the Smart Watcher create one for each plugin)
private List<FileSystemWatcher> _lstWatchers = new List<FileSystemWatcher>();

// FileProcessor is the class which maintains a queue of files to be processed and controls a worker thread which processes each file in the queue.
static FileProcessor processor;

#endregion  

Methods:  

#region Methods

// this function is responsible a about looking for plugins
// into Plugin folder and add them the Smart Wacher plugins list (ipi)
private void LoadPlugIns()

// After Smart Watcher detect its plugins it call this function to create
// a SystemFileWatcher for each plugin and initialize it with plugin sttings.
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

        // intilaize files processor to maintains files queue 
        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))
    {
        //ToDo: Add Handle Exception
        return;
    }

    // Check if file is accessble
    if (!WaitReady(filepath, SmartWatcherService.SettingsReadTries))
    {
        //ToDo: Add Log
        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)
    {
        //ToDo: add exception handeling                  
    }
    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))
            {
                // Check if file is accessble
                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. 

Last edited Aug 7, 2013 at 9:55 AM by TammamKoujan, version 3

Comments

No comments yet.