/// <summary> /// Load the CCO options data from the specified XML file and supply it as a filled CCO object. /// </summary> /// <param name="options">The CCO options data as a CCO object.</param> /// <param name="filePath">The path of the file to load the XML options data from.</param> /// <param name="errorTxt">Holds the error message of the Exception if there was an error during load.</param> /// <returns>True if there were no errors, otherwise false.</returns> public bool Load(out CCO options, string filePath, out string errorTxt) { errorTxt = ""; options = new CCO(); try { CCOFunctions optFunc = new CCOFunctions(); // First, create our XmlDocument for storing configuration values XmlDocument doc = new XmlDocument(); // Create the XmlReader that will read the XML document from disk XmlReader reader = XmlReader.Create(filePath); // Read and load it, and close the reader doc.Load(reader); reader.Close(); // Create an XPathNavigator so we can easily query values from the XmlDocument XPathNavigator nav = doc.CreateNavigator(); // Now populate the CCO object from our XmlDocument's values // Backup type XPathNodeIterator typeIter = nav.Select("/carbonCopyOptions/backupType"); if (!typeIter.MoveNext()) { throw new Exception("Couldn't find backupType configuration entry!"); } options.Type = (CCOTypeOfBackup)Convert.ToInt32(typeIter.Current.GetAttribute("value", "")); // Is dry run? XPathNodeIterator dryRunIter = nav.Select("/carbonCopyOptions/isDryRun"); if (!dryRunIter.MoveNext()) { throw new Exception("Couldn't find isDryRun configuration entry!"); } options.IsDryRun = Convert.ToBoolean(dryRunIter.Current.GetAttribute("value", "")); // To display XPathNodeIterator displayIter = nav.Select("/carbonCopyOptions/outputDetail"); if (!displayIter.MoveNext()) { throw new Exception("Couldn't find outputDetail configuration entry!"); } options.OutputDetail = (VerbosityLevel)Convert.ToInt32(displayIter.Current.GetAttribute("value", "")); // Source dirs options.SourceDirs = new List<DirectoryInfo>(); XPathNodeIterator srcIter = nav.Select("/carbonCopyOptions/srcDirs/dir"); while (srcIter.MoveNext()) { string pathString = srcIter.Current.Value; string errorHolder; DirectoryInfo fixedPath = null; // Is path string valid? if (!optFunc.CheckDirValidity(pathString, ref fixedPath, out errorHolder)) { throw new Exception(errorHolder); } options.SourceDirs.Add(fixedPath); } // Dest dir XPathNodeIterator destIter = nav.Select("/carbonCopyOptions/destDir"); if (!destIter.MoveNext()) { throw new Exception("Couldn't find destDir configuration entry!"); } string pathString2 = destIter.Current.GetAttribute("value", ""); string errorHolder2; DirectoryInfo fixedPath2 = null; // Is path string valid? if (!optFunc.CheckDirValidity(pathString2, ref fixedPath2, out errorHolder2)) { throw new Exception(errorHolder2); } options.DestDir = fixedPath2; // Finally, sanity check our populated CCO object string sanityErrors; if (!optFunc.SanityCheck(options, out sanityErrors)) { throw new Exception("Error(s) found in backup profile file:\r\n" + sanityErrors); } } catch (Exception ex) { errorTxt = ex.Message; return false; } return true; }
/// <summary> /// Initial backup process thread method; begins the actual process of backing up specified files to specified backup directory. /// </summary> private void backupWorkerGo() { DirectoryInfo fixedPath = null; string errorHolder; CCOFunctions optFunc = new CCOFunctions(); if (stopBackup) { endBackupCleanup(); return; } // List directory and configuration information foreach (DirectoryInfo di in options.SourceDirs) { AddMsg(new MsgDisplayInfo(CbVerboseMsg, "Found source backup directory: " + di.FullName)); } AddMsg(new MsgDisplayInfo(CbVerboseMsg, "Found destination backup directory: " + options.DestDir.FullName)); AddMsg(new MsgDisplayInfo(CbVerboseMsg, "Type of backup: " + options.Type.ToString())); AddMsg(new MsgDisplayInfo(CbVerboseMsg, "Verbosity level: " + options.OutputDetail.ToString())); // Ensure that all source backup dirs are valid and 'touch them up' // (setting them to fixedPath fixes their capitalization and terminates // them all with a back or forward slash) for (int i=0; i < options.SourceDirs.Count; i++) { if (!optFunc.CheckDirValidity(options.SourceDirs[i].FullName, ref fixedPath, out errorHolder)) { AddMsg(new MsgDisplayInfo(CbErrorMsg, errorHolder)); endBackupCleanup(); return; } else { options.SourceDirs[i] = fixedPath; } } // Ensure that there are no source backup dir dupes foreach (DirectoryInfo di1 in options.SourceDirs) { // Is it a dupe? int dupeCount = 0; foreach (DirectoryInfo di2 in options.SourceDirs) { if (di1.FullName == di2.FullName) { dupeCount++; if (dupeCount > 1) { AddMsg(new MsgDisplayInfo(CbErrorMsg, "Directory '" + di1.FullName + "' is duplicated in the source directories list.")); endBackupCleanup(); return; } } } } // Check that destination backup dir is valid and 'touch it up' if (!optFunc.CheckDirValidity(options.DestDir.FullName, ref fixedPath, out errorHolder)) { AddMsg(new MsgDisplayInfo(CbErrorMsg, errorHolder)); endBackupCleanup(); return; } else { options.DestDir = fixedPath; } if (!options.IsDryRun) { AddMsg(new MsgDisplayInfo(CbInfoMsg, "Starting backup.")); } else { AddMsg(new MsgDisplayInfo(CbInfoMsg, "Starting 'dry run' backup.")); } foreach (DirectoryInfo sourceDir in options.SourceDirs) { if (stopBackup) { endBackupCleanup(); return; } // Backup this source directory tree try { currentlyProcessing = sourceDir.FullName; } catch (Exception) { } if (!options.IsDryRun) { AddMsg(new MsgDisplayInfo(CbInfoMsg, "Synchronizing base source directory " + sourceDir.FullName)); } else { AddMsg(new MsgDisplayInfo(CbInfoMsg, "Would synchronize base source directory " + sourceDir.FullName)); } try { traverseDir(sourceDir, options.DestDir); } catch (StopBackupException) { endBackupCleanup(); return; } catch (Exception ex) { endBackupCleanup(); AddMsg(new MsgDisplayInfo(CbErrorMsg, "BACKUP HALTED... Misc. error occurred: " + ex.Message.ToString())); return; } } // We finished! AddMsg(new MsgDisplayInfo(CbInfoMsg, "Backup finished successfully.")); endBackupCleanup(); return; }