/// <summary>
        /// Loads all the configuration information for the XML file into public fields
        /// </summary>
        private bool ExtractParms(XmlDocument configXml, List<WatchFolder> watchFolders)
        {
            try
            {
                XmlNodeList rootParms = configXml.SelectNodes("EDAfilewatcher");
                WatchFolder watchFolder;

                FileShares = new HashSet<FileShare>();
                UnauthenticatedFileShares = new HashSet<FileShare>();

                if (rootParms == null)
                {
                    Log.Instance.Warn("ExtractParms: No Parms found to process in XML file.");
                    return false;
                }

                foreach (XmlNode xmlNode in rootParms)
                {
                    foreach (XmlNode childNode in xmlNode)
                    {
                        if (childNode.Name.ToUpper() != "FILESHARE")
                            continue;

                        FileShare share = new FileShare();

                        foreach (XmlNode fileShareNode in childNode)
                        {
                            switch (fileShareNode.Name.ToUpper())
                            {
                                case "NAME":
                                    share.Name = fileShareNode.InnerText;
                                    break;

                                case "DOMAIN":
                                    share.Domain = fileShareNode.InnerText;
                                    break;

                                case "USERNAME":
                                    string[] splitUsername = fileShareNode.InnerText.Split('\\');

                                    if (splitUsername.Length > 1)
                                    {
                                        share.Domain = splitUsername[0];
                                        share.Username = splitUsername[1];
                                    }
                                    else
                                    {
                                        share.Username = splitUsername[0];
                                    }

                                    break;

                                case "PASSWORD":
                                    bool encrypted = fileShareNode.Attributes != null && fileShareNode.Attributes.Cast<XmlAttribute>().Any(attr => attr.Name.ToUpper() == "ENCRYPTED" && attr.Value.ParseBoolean());

                                    if (encrypted)
                                        share.Password = fileShareNode.InnerText.Decrypt("0679d9ae-aca5-4702-a3f5-604415096987", CipherStrength.Aes256);
                                    else
                                        share.Password = fileShareNode.InnerText;

                                    break;
                            }
                        }

                        if (TryConnectToFileShare(share))
                            share.Password = null;

                        FileShares.Add(share);
                    }

                    foreach (XmlNode childNode in xmlNode)
                    {
                        switch (childNode.Name.ToUpper())
                        {
                            case "SOURCEROOTPATH":
                                if (!string.IsNullOrEmpty(childNode.InnerText))
                                {
                                    RootPathToWatch = FilePath.GetAbsolutePath(childNode.InnerText.EnsureEnd("\\"));

                                    if (Directory.Exists(RootPathToWatch))
                                    {
                                        Log.Instance.Info("ExtractParms:  Root watch folder " + RootPathToWatch.QuoteWrap() + " is valid and exists.");
                                    }
                                    else
                                    {
                                        if (Path.GetInvalidPathChars().Any(c => RootPathToWatch.Contains(c)))
                                            Log.Instance.Error("ExtractParms:  Root watch folder " + RootPathToWatch.QuoteWrap() + " is not a valid folder name.  Many errors to follow.");
                                        else
                                            Log.Instance.Error("ExtractParms:  Root watch folder " + RootPathToWatch.QuoteWrap() + " does not exist or is not accessable.");
                                    }
                                }
                                else
                                {
                                    RootPathToWatch = "";
                                    Log.Instance.Error("ExtractParms:  Root watch folder is empty.  Many errors to follow.");
                                }
                                break;

                                //case "OUTPUTFILENAMEPATTERN":
                                //    if (!string.IsNullOrEmpty(childNode.InnerText))
                                //    {
                                //        Log.Instance.Debug("ExtractParms: Format Pattern to Parse = " + childNode.InnerText.QuoteWrap());
                                //        OutputFilePatternIsSet = CreateOutputPattern(childNode.InnerText);
                                //    }
                                //    else
                                //    {
                                //        OutputFilePatternIsSet = false;
                                //        Log.Instance.Debug("ExtractParms: No Format Pattern to Parse.");
                                //    }
                                //    if (OutputFilePatternIsSet)
                                //    {
                                //        Log.Instance.Info("ExtractParms:  Output File Pattern = " +
                                //                          childNode.InnerText.QuoteWrap() + " " +
                                //                          _outputDestinationFileElements.Length.ToString() + " elements found.");

                                //    }
                                //    else
                                //    {
                                //        Log.Instance.Warn("ExtractParms:  No or invalid file inPatternString for creating of output files.  Pattern set to default.");
                                //        OutputFilePatternIsSet = CreateOutputPattern("{meterAssetID}_{filename}");
                                //        //if (!OutputFilePatternIsSet)
                                //        //    Log.Instance.Error("ExtractParms: Did not sucessfully parse defalut file inPatternString");

                                //    }
                                //    break;

                                //case "LOGFILEFOLDER":
                                //    if (!string.IsNullOrEmpty(childNode.InnerText))
                                //    {
                                //        _logFolder = childNode.InnerText;

                                //    }
                                //    else
                                //    {
                                //        _logFolder = "ApplicationPath";
                                //    }
                                //   Log.Instance.Info("ExtractParms:  Log file foldername = " + RootPathToWatch);
                                //    break;
                                //case "LOGDETAIL":
                                //    if (!string.IsNullOrEmpty(childNode.InnerText) &&
                                //        childNode.InnerText.ToUpper().Trim() == "VERBOSE")
                                //    {
                                //        _logDetail = LogDetail.Verbose;
                                //    }
                                //    else if (!string.IsNullOrEmpty(childNode.InnerText) &&
                                //             childNode.InnerText.ToUpper().Trim() == "NONE")
                                //    {
                                //        _logDetail = LogDetail.None;
                                //    }
                                //    else if (!string.IsNullOrEmpty(childNode.InnerText) &&
                                //            childNode.InnerText.ToUpper().Trim() == "NORMAL")
                                //    {
                                //        _logDetail = LogDetail.Normal;
                                //    }
                                //    Log.Instance.Info("ExtractParms:  Log Detail = " + _logDetail.ToString());
                                //    break;
                            default:
                                break;
                        }
                    }
                }

                XmlNodeList actionSet = configXml.SelectNodes("EDAfilewatcher/watchActions");
                if (actionSet == null)
                {
                    Log.Instance.Warn("ExtractParms: No watchActions found to process in XML file.");
                    return false;
                }
                foreach (XmlNode action in actionSet)
                {

                    foreach (XmlNode folder in action.ChildNodes)
                    {

                        if (folder.Name.ToUpper() == "FOLDER" && folder.Attributes != null && folder.Attributes.Count >= 1)
                            //each folder tag must have at least one attribute, the "name" of the folder.
                        {
                            Log.Instance.Debug("ExtractParms:  Proessing XML for folder = " + folder.Attributes[0].Value.Trim());

                            string filter = "";
                            string folderToProcess = "";
                            bool subfolders = false;
                            bool createFwrXml = true; //default is true.
                            Meter nodeMeter = new Meter();

                            foreach (XmlAttribute a in folder.Attributes)
                            {
                                switch (a.Name.ToUpper())
                                {
                                    case "NAME":
                                        folderToProcess = a.Value;
                                        break;
                                }
                            }

                            //XML can be in any order, need the static filter and subfolders info first (neither is necessary)
                            foreach (XmlNode xmlNode in folder.ChildNodes)
                            {
                                Log.Instance.Debug("ExtractParms:  Proessing Node " + xmlNode.Name.Trim() + "   InnerText = " + xmlNode.InnerText.Trim().QuoteWrap());
                                switch (xmlNode.Name.ToUpper())
                                {
                                    case "FILEFILTER":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            filter = xmlNode.InnerText.Trim();
                                        }
                                        else
                                        {
                                            filter = "";
                                        }
                                        break;
                                    case "INCLUDESUBFOLDERS":
                                        if (xmlNode.InnerText.ParseBoolean())
                                        {
                                            subfolders = true;
                                        }
                                        else
                                        {
                                            subfolders = false;
                                        }
                                        break;
                                        break;
                                    case "PRODUCERESULTSXML":
                                        if (xmlNode.InnerText.ParseBoolean())
                                        {
                                            createFwrXml = true;
                                        }
                                        else
                                        {
                                            createFwrXml = false;
                                        }
                                        break;
                                    case "METERNAME":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.Name = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERSN":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.SN = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERALIAS":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.Alias = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERASSETID":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.AssetID = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERVENDOR":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.Vendor = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERMODEL":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.Model = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERSUBSTATIONID":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.StationID = xmlNode.InnerText.Trim();
                                        }
                                        break;
                                    case "METERSUBSTATIONNAME":
                                        if (!string.IsNullOrEmpty(xmlNode.InnerText))
                                        {
                                            nodeMeter.StationName = xmlNode.InnerText.Trim();
                                        }
                                        break;

                                }
                            }

                            //now process each action
                            foreach (XmlNode actionParm in folder.ChildNodes)
                            {
                                switch (actionParm.Name.ToUpper())
                                {
                                    case "WATCHCREATED":
                                    case "WATCHRENAMED":
                                    case "WATCHDELETED":
                                    case "WATCHCHANGED":
                                        watchFolder = new WatchFolder();

                                        foreach (XmlAttribute a in actionParm.Attributes)
                                        {
                                            switch (a.Name.ToUpper())
                                            {
                                                case "ACTION":
                                                    if (a.Value.ToUpper() == "NOTIFY")
                                                        watchFolder.WatchFolderAction.Action = FileAction.Notify;
                                                    else if (a.Value.ToUpper() == "COPY")
                                                        watchFolder.WatchFolderAction.Action = FileAction.Copy;
                                                    else if (a.Value.ToUpper() == "MOVE")
                                                        watchFolder.WatchFolderAction.Action = FileAction.Move;
                                                    else
                                                        watchFolder.WatchFolderAction.Action = FileAction.None;
                                                    Log.Instance.Debug("ExtractParms: Action Parsed " + a.Name + " = " + a.Value);
                                                    break;
                                                case "DESTINATIONFOLDER":
                                                    watchFolder.WatchFolderAction.OutputFolderPattern = CreateOutputPattern(a.Value);
                                                    if (watchFolder.WatchFolderAction.OutputFolderPattern == null)
                                                    {
                                                        Log.Instance.Warn("ExtractParms: Destination Folder Not Parsed Successfully for " + a.Name + " = " + a.Value.QuoteWrap() + "for "
                                                                          + actionParm.Name);
                                                    }
                                                    else
                                                    {
                                                        Log.Instance.Debug("ExtractParms: Destination Folder Parsed " + a.Name + " = " + a.Value.QuoteWrap());
                                                    }

                                                    break;
                                                case "DESTINATIONFILENAME":
                                                    watchFolder.WatchFolderAction.OutputFilePattern = CreateOutputPattern(a.Value);
                                                    if (watchFolder.WatchFolderAction.OutputFilePattern == null)
                                                    {
                                                        Log.Instance.Warn("ExtractParms: Destination Filename Not Parsed Successfully for " + a.Name + " = " + a.Value.QuoteWrap() + "for "
                                                                          + actionParm.Name);
                                                    }
                                                    else
                                                    {
                                                        Log.Instance.Debug("ExtractParms: Destination FileName Parsed " + a.Name + " = " + a.Value.QuoteWrap());
                                                    }
                                                    break;
                                            }
                                        }

                                        watchFolder.WatchFolderAction.Enabled = actionParm.InnerText.ParseBoolean();
                                        watchFolder.WatchSubfolders = subfolders;
                                        watchFolder.ProduceResultsFile = createFwrXml;

                                        watchFolder.FileFilter = filter;
                                        watchFolder.MeterInfo = nodeMeter;

                                        watchFolder.FolderToWatch = folderToProcess;

                                        if (folderToProcess.ToUpper() == "SOURCEROOT")
                                            watchFolder.FullPathToWatch = RootPathToWatch.EnsureEnd("\\");
                                        else
                                            watchFolder.FullPathToWatch = Path.Combine(RootPathToWatch, folderToProcess).EnsureEnd("\\");

                                        if (Path.GetInvalidPathChars().Any(c => watchFolder.FullPathToWatch.Contains(c)))
                                        {
                                            watchFolder.WatchFolderAction.Enabled = false;
                                            Log.Instance.Warn("ExtractParms: Folder specified to watch " + folderToProcess.QuoteWrap() + " is not valid path name.  Folder action skipped.");
                                        }

                                            if (actionParm.Name.ToUpper().IndexOf("CREATED") > 0)
                                            {
                                                watchFolder.WatchFolderAction.EventType =
                                                    FileEventType.Created;
                                            }
                                            else if (actionParm.Name.ToUpper().IndexOf("CHANGED") > 0)
                                            {
                                                watchFolder.WatchFolderAction.EventType =
                                                    FileEventType.Changed;
                                            }
                                            else if (actionParm.Name.ToUpper().IndexOf("DELETED") > 0)
                                            {
                                                watchFolder.WatchFolderAction.EventType =
                                                    FileEventType.Deleted;
                                            }
                                            else if (actionParm.Name.ToUpper().IndexOf("RENAMED") > 0)
                                            {
                                                watchFolder.WatchFolderAction.EventType =
                                                    FileEventType.Renamed;
                                            }

                                        if (actionParm.Attributes != null && actionParm.Attributes.Count >= 1)
                                        {
                                            foreach (XmlAttribute attrib in actionParm.Attributes)
                                                switch (attrib.Name.ToUpper())
                                                {
                                                    case "ACTION":
                                                        if (attrib.Value.ToUpper().IndexOf("NOTIFY") > -1)
                                                            watchFolder.WatchFolderAction.Action = FileAction.Notify;
                                                        else if (attrib.Value.ToUpper().IndexOf("MOVE") > -1)
                                                            watchFolder.WatchFolderAction.Action = FileAction.Move;
                                                        else if (attrib.Value.ToUpper().IndexOf("COPY") > -1)
                                                            watchFolder.WatchFolderAction.Action = FileAction.Copy;
                                                        else
                                                            watchFolder.WatchFolderAction.Enabled = false;

                                                        break;

                                                    case "DESTINATTION":
                                                        // ??  Investigate  Why is this here?
                                                        watchFolder.WatchFolderAction.OutputFolderPattern = CreateOutputPattern(attrib.Value);
                                                        break;
                                                }
                                        }
                                        else
                                        {
                                            watchFolder.WatchFolderAction.Enabled = false;
                                        }

                                        watchFolders.Add(watchFolder);

                                        break;
                                }
                            }
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                Log.Instance.ErrorException("ExtractParms: Cannot parse watchActions in XML configuration file. ", ex);
                return false;
            }
        }
        /// <summary>
        /// Returns TRUE if actions in this folder should be processed
        /// </summary>
        /// <param name="fileSpec">The full file path of this folder</param>
        /// <param name="f">The WatchFolder parms for his candidate action</param>
        /// <returns></returns>
        private bool ProcessThisFolder(string fileSpec, WatchFolder f)
        {
            string folderSpec = Path.GetFullPath(Path.GetDirectoryName(fileSpec).ToNonNullString()).TrimEnd('\\');
            string pathToWatch = Path.GetFullPath(f.FullPathToWatch).TrimEnd('\\');

            if (string.IsNullOrEmpty(folderSpec))
                return false;

            // If watching sub folders, we trim folderSpec down to the same
            // number of characters as the path to watch before we compare
            if (f.WatchSubfolders && (folderSpec.Length > pathToWatch.Length))
                folderSpec = folderSpec.Substring(0, pathToWatch.Length + 1).TrimEnd('\\');

            return (string.Compare(folderSpec, pathToWatch, StringComparison.CurrentCultureIgnoreCase) == 0);
        }
        /// <summary>
        /// 
        /// </summary>
        private DestinationFilePattern[] CreateStaticElements(WatchFolder wf, DestinationFilePattern[] pattern)
        {
            if (wf == null) return null;

            // There is only one WatchAction per WatchFolder

            Log.Instance.Debug("CreateStaticFileNameElements: Processing " + wf.FolderToWatch.QuoteWrap() + " destination folder pattern.");

            foreach (DestinationFilePattern fp in pattern)
            {
                if (fp.IsField)
                {
                    switch (fp.Element)
                    {
                        case "METERNAME":
                            if (string.IsNullOrEmpty(wf.MeterInfo.Name))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.Name;
                            fp.IsField = false;
                            break;
                        case "METERSN":
                            if (string.IsNullOrEmpty(wf.MeterInfo.SN))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.SN;
                            fp.IsField = false;
                            break;
                        case "METERASSETID":
                            if (string.IsNullOrEmpty(wf.MeterInfo.AssetID))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.AssetID;
                            fp.IsField = false;
                            break;
                        case "METERALIAS":
                            if (string.IsNullOrEmpty(wf.MeterInfo.Alias))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.Alias;
                            fp.IsField = false;
                            break;
                        case "METERSUBSTATATIONNAME":
                            if (string.IsNullOrEmpty(wf.MeterInfo.StationName))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.StationName;
                            fp.IsField = false;
                            break;
                        case "METERVENDOR":
                            if (string.IsNullOrEmpty(wf.MeterInfo.Vendor))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.Vendor;
                            fp.IsField = false;
                            break;
                        case "METERSUBSTATIONID":
                            if (string.IsNullOrEmpty(wf.MeterInfo.StationID))
                                fp.PathPieceText = "";
                            else
                                fp.PathPieceText = wf.MeterInfo.StationID;
                            fp.IsField = false;
                            break;
                        case "APPPATH":
                            fp.PathPieceText = Path.GetDirectoryName(Assembly.GetAssembly(typeof(XDAFileWatcher)).CodeBase);
                            fp.IsField = false;
                            break;
                    }
                }
                else
                {
                    // Not a field
                    fp.PathPieceText = fp.Element;
                }
            }
            return pattern;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="filespec"></param>
        /// <param name="f"></param>
        /// <returns></returns>
        private bool ProcessThisFilename(string filespec, WatchFolder f)
        {
            string filename = FilePath.GetFileName(filespec);
            string[] patterns;
            string regex;

            if (string.IsNullOrEmpty(filename))
                return false;

            patterns = f.FileFilter.Split(_separators);

            foreach (string pattern in patterns)
            {
                regex = Regex.Escape(pattern.Trim()).Replace("\\*", ".*").Replace("\\?", ".");

                if (Regex.IsMatch(filename, regex, RegexOptions.IgnoreCase))
                    return true;
            }

            return false;
        }