Example #1
1
        public void DoAddTasks(bool abStartup)
        {
            // Do this at most once per minute to avoid running the same task twice in rapid succession.
            if ( !abStartup && (!moProfile.ContainsKey("-AddTasks") || DateTime.Now < mdtPreviousAddTasksStarted.AddMinutes(1)) )
                return;

            mdtPreviousAddTasksStarted = DateTime.Now;

            try
            {
                if ( null == moAddTasksProfile )
                {
                    moAddTasksProfile = moProfile.oProfile("-AddTasks").oOneKeyProfile("-Task");
                    moAddTasksProcessArray = new Process[moAddTasksProfile.Count];
                }
                
                for (int i=0; i < moAddTasksProfile.Count; ++i)
                {
                    // Convert the current task from a command-line string to a profile oject.
                    tvProfile loAddTask = new tvProfile(moAddTasksProfile[i].ToString());

                    bool lbDoTask = false;

                    if ( abStartup )
                    {
                        lbDoTask = loAddTask.bValue("-OnStartup", false);

                        // Reset pause timer to allow other tasks to run without delay after startup.
                        mdtPreviousAddTasksStarted = DateTime.Now.AddMinutes(-1);
                    }
                    else
                    {
                        DateTime    ldtTaskStartTime = loAddTask.dtValue("-StartTime", DateTime.MinValue);
                        string      lsTaskDaysOfWeek = loAddTask.sValue("-StartDays", "");

                        // If -StartTime is within the current minute, start the task.
                        // If -StartDays is specified, run the task on those days only.
                        lbDoTask = DateTime.MinValue != ldtTaskStartTime && (int)mdtPreviousAddTasksStarted.TimeOfDay.TotalMinutes == (int)ldtTaskStartTime.TimeOfDay.TotalMinutes
                                && ("" == lsTaskDaysOfWeek || this.bListIncludesDay(lsTaskDaysOfWeek, mdtPreviousAddTasksStarted));
                    }

                    if ( lbDoTask )
                    {
                        string  lsCommandEXE = loAddTask.sValue("-CommandEXE", "add task -CommandEXE missing");

                        Process loProcess = new Process();
                                loProcess.ErrorDataReceived += new DataReceivedEventHandler(this.BackupProcessOutputHandler);
                                loProcess.OutputDataReceived += new DataReceivedEventHandler(this.BackupProcessOutputHandler);
                                loProcess.StartInfo.FileName = lsCommandEXE;
                                loProcess.StartInfo.Arguments = loAddTask.sValue("-CommandArgs", "");
                                loAddTask.bValue("-UnloadOnExit", false);

                                // The following subset of parameters are overridden when -TimeoutMinutes is set. This is
                                // necessary to guarantee IO redirection is handled properly (ie. output goes to the log).
                        bool    lbWaitForExitOverride = (loAddTask.iValue("-TimeoutMinutes", 0) > 0);
                                loProcess.StartInfo.CreateNoWindow          =  lbWaitForExitOverride | loAddTask.bValue("-CreateNoWindow", false);
                                loProcess.StartInfo.UseShellExecute         = !lbWaitForExitOverride & loAddTask.bValue("-UseShellExecute", true);
                                loProcess.StartInfo.RedirectStandardInput   =  lbWaitForExitOverride | loAddTask.bValue("-RedirectStandardInput", false);
                                loProcess.StartInfo.RedirectStandardError   =  lbWaitForExitOverride | loAddTask.bValue("-RedirectStandardError", false);
                                loProcess.StartInfo.RedirectStandardOutput  =  lbWaitForExitOverride | loAddTask.bValue("-RedirectStandardOutput", false);

                                moAddTasksProcessArray[i] = loProcess;

                        try
                        {
                            if ( !loAddTask.bValue("-OnStartup", false) )
                            {
                                this.LogIt(String.Format("Starting Task: {0}", loAddTask.sCommandLine()));

                                loProcess.Start();

                                // Start output to console also.
                                if ( loProcess.StartInfo.RedirectStandardError )
                                    loProcess.BeginErrorReadLine();
                                if ( loProcess.StartInfo.RedirectStandardOutput )
                                    loProcess.BeginOutputReadLine();

                                if ( lbWaitForExitOverride )
                                {
                                    // Wait the timeout period, then call "WaitForExit()" to flush the output steams.
                                    if ( loProcess.WaitForExit(60000 * loAddTask.iValue("-TimeoutMinutes", 0)) )
                                        loProcess.WaitForExit();

                                    // Stop output to console.
                                    if ( loProcess.StartInfo.RedirectStandardError )
                                        loProcess.CancelErrorRead();
                                    if ( loProcess.StartInfo.RedirectStandardOutput )
                                        loProcess.CancelOutputRead();

                                    loProcess.Close();
                                }
                            }
                            else
                            {
                                bool        lbFound = false;
                                string      lsWindowTitle = loAddTask.sValue("-CommandWindowTitle", "");
                                Process[]   loProcessesArray = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(loProcess.StartInfo.FileName));
                                            // If there's exactly one matching process and no given window title to compare, we're done.
                                            lbFound = (1 == loProcessesArray.Length && "" == lsWindowTitle );

                                            // If no window title has been given to compare, there's nothing else to do.
                                            if ( !lbFound && "" != lsWindowTitle )
                                            {
                                                // If no matching processes have been found so far, get them all to compare.
                                                if ( 0 == loProcessesArray.Length )
                                                    loProcessesArray = Process.GetProcesses();

                                                // Since a window title has been provided, it must be compared to the process(es) found.
                                                // Wildcards are permitted, but only at the end of titles. We stop at the first match.
                                                foreach (Process loProcessEntry in loProcessesArray)
                                                    if ( loProcessEntry.MainWindowTitle.StartsWith(lsWindowTitle.Replace("*", "")) )
                                                    {
                                                        lbFound = true;
                                                        break;
                                                    }
                                            }

                                // Don't start -OnStartup processes that have already been started.
                                if ( lbFound )
                                {
                                    // The process has "already started" if there is only one with the
                                    // same EXE or multiple EXEs with one having the same window title.
                                    this.LogIt(String.Format("Already running, task not started: {0}", loAddTask.sCommandLine()));
                                }
                                else
                                {
                                    this.LogIt(String.Format("Starting Task: {0}", loAddTask.sCommandLine()));

                                    loProcess.Start();

                                    // Start output to console also.
                                    if ( loProcess.StartInfo.RedirectStandardError )
                                        loProcess.BeginErrorReadLine();
                                    if ( loProcess.StartInfo.RedirectStandardOutput )
                                        loProcess.BeginOutputReadLine();

                                    if ( lbWaitForExitOverride )
                                    {
                                        // Wait the timeout period, then call "WaitForExit()" to flush the output steams.
                                        if ( loProcess.WaitForExit(60000 * loAddTask.iValue("-TimeoutMinutes", 0)) )
                                            loProcess.WaitForExit();

                                        // Stop output to console.
                                        if ( loProcess.StartInfo.RedirectStandardError )
                                            loProcess.CancelErrorRead();
                                        if ( loProcess.StartInfo.RedirectStandardOutput )
                                            loProcess.CancelOutputRead();

                                        loProcess.Close();
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            this.ShowError(ex.Message, String.Format("Failed starting task: {0}", lsCommandEXE));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.ShowError(ex.Message, "Add Tasks Failed");
            }
        }
Example #2
0
        /// <summary>
        /// Recursively deletes files of the given path\file
        /// specification older than the given age in days.
        /// </summary>
        /// <param name="asPathFiles">
        /// The path\file specification of files to be deleted.
        /// </param>
        /// <param name="adtOlderThan">
        /// Files with timestamps older than this will be deleted.
        /// </param>
        /// <param name="aeFileDateTimeType">
        /// Each file has multiple timestamps. This specifies which one to use.
        /// </param>
        /// <param name="aoProfile">
        /// This profile contains the various cleanup parameters.
        /// </param>
        public bool CleanupPathFileSpec(
                  string asPathFiles
                , DateTime adtOlderThan
                , FileDateTimeTypes aeFileDateTimeType
                , tvProfile aoProfile
                )
        {
            if ( this.bMainLoopStopped )
                return true;

            bool    lbCleanupPathFileSpec = true;
            string  lsPath = Path.GetDirectoryName(asPathFiles);
            string  lsFiles = Path.GetFileName(asPathFiles);
            bool    lbCleanupHidden = aoProfile.bValue("-CleanupHidden", false);
            bool    lbCleanupReadOnly = aoProfile.bValue("-CleanupReadOnly", false);
            bool    lbRecurse = aoProfile.bValue("-Recurse", false);
/*
            bool    lbDisplayFileDeletionErrors = true;
                    // Don't create a default value here. Let the user create the value via a prompt
                    // below. This must be handled this way since the deletion error messages are 
                    // modeless and therefore the "skip this" checkbox will be presented only once.
                    if ( moProfile.ContainsKey("-MsgBoxPromptFileDeletionErrors") )
                        lbDisplayFileDeletionErrors = moProfile.bValue("-MsgBoxPromptFileDeletionErrors", true);
*/
            bool    lbDisplayFileDeletionErrors = moProfile.bValue("-MsgBoxPromptFileDeletionErrors", false);
            string  lsDirectorySeparatorChar = Path.DirectorySeparatorChar.ToString();
            string  lsRecurseFolder = aoProfile.sValue("-RecurseFolder", "");
                    // The recurse folder must be surrounded by path delimiters. Otherwise,
                    // a matching path name substring may be found instead of a subfolder name.
                    if ( !lsRecurseFolder.StartsWith(lsDirectorySeparatorChar) )
                        lsRecurseFolder = lsDirectorySeparatorChar + lsRecurseFolder;
                    if ( !lsRecurseFolder.EndsWith(lsDirectorySeparatorChar) )
                        lsRecurseFolder += lsDirectorySeparatorChar;

            try
            {
                // Only check for file cleanup if either there is no recursion
                // or the base path contains the recursion subfolder. An empty
                // recursion subfolder matches everything from the base path up.
                if ( !lbRecurse || (lbRecurse && (lsPath + lsDirectorySeparatorChar).Contains(lsRecurseFolder)) )
                {
                    IOrderedEnumerable<FileSystemInfo> loFileSysInfoList = null;
                            // If the given file path does not exist, do nothing.
                            if ( Directory.Exists(lsPath) )
                                try
                                {
                                    // Get a list of all files for potential deletion
                                    // sorted by file date (oldest files first).
                                    switch (aeFileDateTimeType)
                                    {
                                        case FileDateTimeTypes.CreationTime:
                                            loFileSysInfoList =
                                                    new DirectoryInfo(lsPath).GetFileSystemInfos(lsFiles)
                                                    .OrderBy(a => a.CreationTime);
                                            break;
                                        case FileDateTimeTypes.LastAccessTime:
                                            loFileSysInfoList =
                                                    new DirectoryInfo(lsPath).GetFileSystemInfos(lsFiles)
                                                    .OrderBy(a => a.LastAccessTime);
                                            break;
                                        default:
                                            loFileSysInfoList =
                                                    new DirectoryInfo(lsPath).GetFileSystemInfos(lsFiles)
                                                    .OrderBy(a => a.LastWriteTime);
                                            break;
                                    }
                                }
                                catch (Exception ex)
                                {
                                    if ( !lbDisplayFileDeletionErrors )
                                        this.LogIt(string.Format("Folder: \"{0}\"\r\n", lsPath) + ex.Message);
                                    else
                                        this.ShowModelessError(
                                                  string.Format("Folder: \"{0}\"\r\n", lsPath) + ex.Message
                                                , "Error Deleting Files"
                                                , "-FileDeletionErrors"
                                                );
                                }

                    if ( null != loFileSysInfoList )
                    {
                        // This boolean prevents wiping out many old files
                        // that are not regularly replaced with newer files.
                        bool    lbApplyDeletionLimit = aoProfile.bValue("-ApplyDeletionLimit", true);
                        int     liFileDeletionLimit = this.iFileDeletionLimit(
                                        loFileSysInfoList.Count(), adtOlderThan);
                        int     liIndex = 0;

                        foreach (FileSystemInfo loFileSysInfo in loFileSysInfoList)
                        {
                            System.Windows.Forms.Application.DoEvents();
                            System.Threading.Thread.Sleep(moProfile.iValue("-CleanupLoopSleepMS", 1));
                            if ( this.bMainLoopStopped )
                                break;

                            // Show UI activity for each file evaluated.
                            this.IncrementUIProgressBar();

                            // Since files are deleted in file date order,
                            // the oldest files will always be deleted first.
                            // Once the deletion limit is reached, stop deleting.
                            if ( lbApplyDeletionLimit && ++liIndex > liFileDeletionLimit )
                                break;

                            DateTime ldtFileDate;
                                    switch (aeFileDateTimeType)
                                    {
                                        case FileDateTimeTypes.CreationTime:
                                            ldtFileDate = loFileSysInfo.CreationTime;
                                            break;
                                        case FileDateTimeTypes.LastAccessTime:
                                            ldtFileDate = loFileSysInfo.LastAccessTime;
                                            break;
                                        default:
                                            ldtFileDate = loFileSysInfo.LastWriteTime;
                                            break;
                                    }
                            // Delete the current file only if its file date is older
                            // than the given date. If it's also a hidden file, the
                            // -CleanupHidden switch must be specified (see above).
                            bool lbDoDelete = ldtFileDate < adtOlderThan
                                    && (    lbCleanupHidden
                                        ||  FileAttributes.Hidden
                                        !=  (loFileSysInfo.Attributes & FileAttributes.Hidden));

                            if ( lbDoDelete )
                            {
                                try 
                                {	        
                                    // Get the file size.
                                    long llFileSize = new FileInfo(loFileSysInfo.FullName).Length;

                                    // If the -CleanupReadOnly switch is used (see above),
                                    // set the current file's attributes to "Normal".
                                    if (        lbCleanupReadOnly
                                            &&  FileAttributes.ReadOnly
                                            ==  (loFileSysInfo.Attributes & FileAttributes.ReadOnly)
                                            )
                                        loFileSysInfo.Attributes = FileAttributes.Normal;

                                    // Hidden files can be deleted without changing attributes.

                                    // Attempt to delete the file. If its attributes still
                                    // include "readonly", let it blow an error.
                                    loFileSysInfo.Delete();

                                    this.LogDeletedFile(loFileSysInfo.FullName, ldtFileDate, llFileSize);
                                }
                                catch (Exception ex)
                                {
                                    if ( !lbDisplayFileDeletionErrors )
                                        this.LogIt(string.Format("File: \"{0}\"\r\n", loFileSysInfo.FullName) + ex.Message);
                                    else
                                        this.ShowModelessError(
                                                  string.Format("File: \"{0}\"\r\n", loFileSysInfo.FullName) + ex.Message
                                                , "Error Deleting File"
                                                , "-FileDeletionErrors"
                                                );
                                }
                            }
                        }
                    }
                }

                // Recursion is determined by the -Recurse switch (see above).
                if ( lbRecurse )
                {
                    // Process the sub-folders in the base folder.

                    // Use an empty array instead of null to
                    // prevent the "foreach" from blowing up.
                    string[]    lsSubfoldersArray = new string[0];
                                if ( Directory.Exists(lsPath) )
                                {
                                    try
                                    {
                                        // Get subdirectories only at the next level.
                                        lsSubfoldersArray = Directory.GetDirectories(lsPath);
                                    }
                                    catch (Exception ex)
                                    {
                                        if ( !lbDisplayFileDeletionErrors )
                                            this.LogIt(string.Format("Folder: \"{0}\"\r\n", lsPath) + ex.Message);
                                        else
                                            this.ShowModelessError(
                                                      string.Format("Folder: \"{0}\"\r\n", lsPath) + ex.Message
                                                    , "Error Deleting Folders"
                                                    , "-FileDeletionErrors"
                                                    );
                                    }
                                }

                    foreach (string lsSubfolder in lsSubfoldersArray)
                    {
                        System.Windows.Forms.Application.DoEvents();
                        if ( this.bMainLoopStopped )
                            break;

                        // Get the current subfolder's attributes. Using "Hidden" by default prevents
                        // an attempt at deleting the file if its attributes can't be read for whatever
                        // reason (unless the -CleanupHidden switch is used). In the case of unreadable
                        // attributes the file would not likely be deletable anyway.
                        FileAttributes  loFileAttributes = FileAttributes.Hidden;
                                try
                                {
                                    loFileAttributes = File.GetAttributes(lsSubfolder);
                                }
                                catch (Exception ex)
                                {
                                    if ( !lbDisplayFileDeletionErrors )
                                        this.LogIt(string.Format("Folder: \"{0}\"\r\n", lsSubfolder) + ex.Message);
                                    else
                                        this.ShowModelessError(
                                                  string.Format("Folder: \"{0}\"\r\n", lsSubfolder) + ex.Message
                                                , "Error Deleting Folder"
                                                , "-FileDeletionErrors"
                                                );
                                }

                        if (        lbCleanupHidden
                                ||  FileAttributes.Hidden
                                !=  (loFileAttributes & FileAttributes.Hidden)
                                )
                        {
                            // Remove all applicable files in the current subfolder.
                            this.CleanupPathFileSpec(
                                      Path.Combine(lsSubfolder, lsFiles)
                                    , adtOlderThan
                                    , aeFileDateTimeType
                                    , aoProfile
                                    );

                            // This is deliberate. Do not use "Path.Combine()" here. We need
                            // the trailing directory separator character (eg. the backslash)
                            // since the recurse folder will always have a trailing separator.
                            string lsSubfolderPlus = lsSubfolder + lsDirectorySeparatorChar;

                            // Remove empty subfolders in the recurse folder only (ie.
                            // do not remove the recurse folder itself). In other words,
                            // lsSubfolderPlus may contain lsRecurseFolder, but it can't
                            // end with it (unless lsRecurseFolder is just a backslash).
                            if (              lsSubfolderPlus.Contains(lsRecurseFolder)
                                    && (     !lsSubfolderPlus.EndsWith(lsRecurseFolder)
                                        || lsDirectorySeparatorChar == lsRecurseFolder)
                                    )
                            {
                                // These are used to judge the subfolder emptiness.
                                string[]    lsPathFilesArray = new string[0];
                                string[]    lsSubfoldersArray2 = new string[0];
                                        if ( Directory.Exists(lsSubfolder) )
                                            try
                                            {
                                                lsPathFilesArray = Directory.GetFiles(lsSubfolder);
                                                lsSubfoldersArray2 = Directory.GetDirectories(lsSubfolder);
                                            }
                                            catch (Exception ex)
                                            {
                                                if ( !lbDisplayFileDeletionErrors )
                                                    this.LogIt(string.Format("Folder: \"{0}\"\r\n", lsSubfolder) + ex.Message);
                                                else
                                                    this.ShowModelessError(
                                                              string.Format("Folder: \"{0}\"\r\n", lsSubfolder) + ex.Message
                                                            , "Error Deleting Files"
                                                            , "-FileDeletionErrors"
                                                            );
                                            }

                                // Remove the folder only if it's empty.
                                if ( 0 == lsPathFilesArray.Length && 0 == lsSubfoldersArray2.Length )
                                {
                                    DirectoryInfo   loDirInfo = new DirectoryInfo(lsSubfolder);
                                    DateTime        ldtFileDate;
                                            switch (aeFileDateTimeType)
                                            {
                                                case FileDateTimeTypes.CreationTime:
                                                    ldtFileDate = loDirInfo.CreationTime;
                                                    break;
                                                case FileDateTimeTypes.LastAccessTime:
                                                    ldtFileDate = loDirInfo.LastAccessTime;
                                                    break;
                                                default:
                                                    ldtFileDate = loDirInfo.LastWriteTime;
                                                    break;
                                            }

                                    try 
                                    {	        
                                        // If the -CleanupReadOnly switch is used,
                                        // set the subfolder to "Normal" attributes.
                                        if (        lbCleanupReadOnly
                                                &&  FileAttributes.ReadOnly
                                                    == (loFileAttributes & FileAttributes.ReadOnly)
                                                )
                                            File.SetAttributes(lsSubfolder, FileAttributes.Normal);

                                        // Hidden folders can be deleted without changing attributes.

                                        // Attempt to delete the subfolder. If its attributes still
                                        // include "readonly", let it blow an error.
                                        Directory.Delete(lsSubfolder);

                                        // Using "0" as the file size also indicates a folder deletion.
                                        this.LogDeletedFile(lsSubfolder + " (dir)", ldtFileDate, 0);
                                    }
                                    catch (Exception ex)
                                    {
                                        if ( !lbDisplayFileDeletionErrors )
                                            this.LogIt(string.Format("Folder: \"{0}\"\r\n", lsSubfolder) + ex.Message);
                                        else
                                            this.ShowModelessError(
                                                      string.Format("Folder: \"{0}\"\r\n", lsSubfolder) + ex.Message
                                                    , "Error Deleting Folder"
                                                    , "-FileDeletionErrors"
                                                    );
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                this.ShowError(ex.Message, "Unanticipated Error");

                lbCleanupPathFileSpec = false;
            }

            return lbCleanupPathFileSpec;
        }
Example #3
0
        /// <summary>
        /// Deletes files greater than the given age
        /// days and of the given file specifications.
        /// </summary>
        public bool CleanupFiles()
        {
            // Return if cleanup is disabled.
            if ( !moProfile.bValue("-CleanupFiles", true) )
            {
                this.LogIt("");
                this.LogIt("Cleanup files is disabled.");
                return true;
            }
            // Return if backup is enabled and it was stopped.
            if (  moProfile.bValue("-BackupFiles", true) && this.bMainLoopStopped )
                return true;
            else
                this.bMainLoopStopped = false;

            bool lbCleanupFiles = true;

            this.LogIt("");
            this.LogIt("File cleanup started ...");

            // Write the deleted file list header to disk.
            string  lsDeletedFileListOutputPathFile = moProfile.sRelativeToProfilePathFile(this.sDeletedFileListOutputPathFile);

            if ( !File.Exists(lsDeletedFileListOutputPathFile) )
            {
                // Get the column header array.
                string[] lsColumnHeaderArray = moProfile.sValue("-DeletedFileListOutputColumnHeaderArray", "Deleted File Time,File Size,Former File Location").Split(',');

                StreamWriter loStreamWriter = null;

                try
                {
                    loStreamWriter = new StreamWriter(lsDeletedFileListOutputPathFile, false);

                    // First, output the file header.
                    loStreamWriter.WriteLine(string.Format(moProfile.sValue("-DeletedFileListOutputHeader"
                            , "{0, -10:MM-dd-yyyy} File Cleanup List"), DateTime.Today));
                    loStreamWriter.WriteLine();

                    // Next output the column headers properly formatted to match the forthcoming data rows.
                    loStreamWriter.WriteLine(string.Format(
                              moProfile.sValue("-DeletedFileListOutputColumnFormat", "{0, -22:MM-dd-yyyy hh:mm:ss tt}  {1, 13:#,#}  {2}")
                            , lsColumnHeaderArray[0], lsColumnHeaderArray[1], lsColumnHeaderArray[2]));
                    loStreamWriter.WriteLine();
                }
                catch (Exception ex)
                {
                    this.ShowError(string.Format("File Write Failure: \"{0}\"\r\n"
                            , lsDeletedFileListOutputPathFile) + ex.Message
                            , "Failed Writing File"
                            );
                }
                finally
                {
                    if ( null != loStreamWriter )
                        loStreamWriter.Close();
                }
            }

            try
            {
                // This is used elsewhere to warn users if the software
                // has not been properly configured for file cleanups.
                this.mbHasNoDeletionGroups = true;

                if ( !moProfile.ContainsKey("-CleanupSet") )
                {
                    // Create the default file cleanup sets.

                    // Get the primary backup set (ie. the 1st).
                    tvProfile loBackupSet1Profile = new tvProfile(moProfile.sValue("-BackupSet", "(not set)"));
                    string lsBackupOutputPathFileBase = this.sBackupOutputPathFileBase(loBackupSet1Profile);
                    string lsBackupOutputPath = Path.GetDirectoryName(lsBackupOutputPathFileBase);
                    string lsBackupOutputFilenameNoExt = Path.GetFileNameWithoutExtension(lsBackupOutputPathFileBase);

                    // Initially set the cleanup of primary backups to "no cleanup" (ie. 1000 years).
                    // The deletion limit prevents old file removal without new files to replace them.
                    moProfile.Add("-CleanupSet", string.Format(@"
    -AgeDays=365000
    -FilesToDelete={0}*{1}

"
                            , Path.Combine(lsBackupOutputPath, lsBackupOutputFilenameNoExt)
                            , Path.GetExtension(lsBackupOutputPathFileBase)
                            ));

                    // Set the cleanup of temporary backup files to 0 days.
                    // This is necessary to cleanup after killed processes.
                    moProfile.Add("-CleanupSet", string.Format(@"
    -AgeDays=0
    -FilesToDelete={0}.tmp*

"
                            , Path.Combine(this.sArchivePath(), "*" + Path.GetExtension(lsBackupOutputPathFileBase))
                            ));

                    // Set the cleanup of file lists and backup / cleanup log files to 30 days.
                    moProfile.Add("-CleanupSet", string.Format(@"
    -AgeDays=30
    -FilesToDelete={0}
    -FilesToDelete={1}

"
                            , Path.Combine(Path.GetDirectoryName(this.sZipToolFileListPathFileBase)
                                    , "*" + Path.GetExtension(this.sZipToolFileListPathFileBase))

                            , Path.Combine(Path.GetDirectoryName(this.sLogPathFileBase)
                                    , "*" + Path.GetExtension(this.sLogPathFileBase))
                            ));
                }

                // Get all cleanup sets.
                tvProfile loCleanupSetsProfile = moProfile.oOneKeyProfile("-CleanupSet");

                foreach (DictionaryEntry loEntry in loCleanupSetsProfile)
                {
                    System.Windows.Forms.Application.DoEvents();
                    if ( this.bMainLoopStopped )
                        break;

                    // Convert the current cleanup set from a command-line string to a profile oject.
                    tvProfile loCurrentCleanupSet = new tvProfile(loEntry.Value.ToString());

                    // The default "LastWriteTime" is the last modified datetime.
                    FileDateTimeTypes leFileDateTimeType;
                            switch (loCurrentCleanupSet.sValue("-DeletedFileListDateTimeType", "LastWriteTime"))
                            {
                                case "CreationTime":
                                    leFileDateTimeType = FileDateTimeTypes.CreationTime;
                                    break;
                                case "LastAccessTime":
                                    leFileDateTimeType = FileDateTimeTypes.LastAccessTime;
                                    break;
                                default:
                                    leFileDateTimeType = FileDateTimeTypes.LastWriteTime;
                                    break;
                            }
                    // Use 1000 years as the default file age.
                    int         liAgeDays = loCurrentCleanupSet.iValue("-AgeDays", 365000);
                                liAgeDays = 0 == liAgeDays ? -1 : liAgeDays;
                                // "0" means "delete everything." -1 makes that happen.
                    DateTime    ldtOlderThan = DateTime.Now.AddDays(-liAgeDays);

                    // Get the list of path\file specifications to delete.
                    tvProfile loFilesToDeleteProfile = loCurrentCleanupSet.oOneKeyProfile("-FilesToDelete");

                    foreach (DictionaryEntry loPathFilesEntry in loFilesToDeleteProfile)
                    {
                        System.Windows.Forms.Application.DoEvents();
                        if ( this.bMainLoopStopped )
                            break;

                        // Being here means there is at least one set of files to delete.
                        this.mbHasNoDeletionGroups = false;

                        if ( lbCleanupFiles )
                            lbCleanupFiles = this.CleanupPathFileSpec(
                                      moProfile.sRelativeToProfilePathFile(loPathFilesEntry.Value.ToString())
                                    , ldtOlderThan
                                    , leFileDateTimeType
                                    , loCurrentCleanupSet
                                    );
                    }
                }

                if ( lbCleanupFiles )
                    this.DisplayDeletedFileList();
            }
            catch (Exception ex)
            {
                this.ShowError(ex.Message, "Unanticipated Error");

                lbCleanupFiles = false;
            }

            if ( this.bMainLoopStopped )
            {
                this.LogIt("Cleanup process stopped.");
                this.bMainLoopStopped = false;
                lbCleanupFiles = false;
            }
            else
            {
                if ( lbCleanupFiles )
                    this.LogIt("File cleanup finished.");
                else
                    this.LogIt("File cleanup failed.");
            }

            return lbCleanupFiles;
        }
Example #4
0
        public void BackupFailedScript()
        {
            // Before the "backup failed" script can be initialized,
            // -BackupFailedScriptPathFile and -BackupFailedScriptHelp
            // must be initialized first.
            if ( moProfile.bValue("-BackupFailedScriptInit", false) )
            {
                moProfile.Remove("-BackupFailedScriptPathFile");
                moProfile.Remove("-BackupFailedScriptHelp");
            }

            string  lsBackupFailedScriptPathFile = moProfile.sRelativeToProfilePathFile(
                    moProfile.sValue("-BackupFailedScriptPathFile", msBackupFailedScriptPathFileDefault));
            string  lsBackupFailedScriptOutputPathFile = lsBackupFailedScriptPathFile + ".txt";

            // If the "backup failed" script has not been redefined to point elsewhere,
            // prepare to create it from the current -BackupFailedScriptHelp content.
            // We do this even if the script file actually exists already. This way
            // the following default script will be written to the profile file if
            // it's not already there.
            if ( lsBackupFailedScriptPathFile == moProfile.sRelativeToProfilePathFile(msBackupFailedScriptPathFileDefault) )
            {
                string  lsBackupFailedScript = moProfile.sValue("-BackupFailedScriptHelp", @"
@echo off
if %1=="""" goto :EOF
::
:: *** ""Backup Failed"" script goes here. ***
::
:: This script is executed after each backup fails to complete. If you 
:: prompt for input within this DOS script (eg. ""pause""), the script
:: will stay in memory. This is not recommended since such behavior would
:: be similar to a memory leak.
::
:: You can also create and edit another DOS script file and reference that
:: instead (see ""-BackupFailedScriptPathFile"" in ""{ProfileFile}""). You
:: can access several parameters from the completed backup via the DOS shell
:: command-line:
::
:: %1 = ""BackupOutputPathFile""
::
::      This is the full path\file specification of the backup file.
::      It includes the output filename as well as the embedded date.
::
:: %2 = ""BackupOutputFilename""
::
::      This is the backup filename only (ie. no path). It includes the
::      embedded date as well as the filename extension.
::
:: %3 = ""BackupBaseOutputFilename""
::
::      This is the backup filename with no path and no date. It's just
::      the base output filename name with the filename extension.
::
:: %4 = ""LocalArchivePath""
::
::      This is the local archive folder.
::
:: %5 = ""VirtualMachineHostArchive""
::
::      This is the virtual machine host archive share name.
::
::
:: Note: All arguments will be passed with double quotation marks included.
::       So don't use quotes here unless you want ""double double"" quotes.
::       Also, ERRORLEVEL is not reliable enough to be heavily used below.
::
:: The following example copies the backup file to the root of drive C:
:: (if it's ""AdministratorFiles.zip""). Then it outputs a directory listing
:: of the archive folder.
::
:: Example:
::
:: if not %3.==""AdministratorFiles.zip"". goto :EOF
::
::     echo copy %1 C:\  ] ""{BackupFailedScriptOutputPathFile}"" 2>&1
::          copy %1 C:\ ]] ""{BackupFailedScriptOutputPathFile}"" 2>&1
::
:: dir %4               ]] ""{BackupFailedScriptOutputPathFile}"" 2>&1
::
::                      ^^  Replace brackets with darts.

:: Initialize the ""backup failed"" script log file. It's for this run only.
echo.                    > ""{BackupFailedScriptOutputPathFile}"" 2>&1


:: Any failed backup file less than this size will be removed.
set MinFileBytes=1024

set Filesize=%~z1

:: This references the backup file by named variable (rather than positionally):
set FileSpec=%1

echo If the failed backup file is smaller than %MinFileBytes% bytes,            >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo it will be removed.                                                        >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo.                                                                           >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo %FileSpec% is %Filesize% bytes.                                            >> ""{BackupFailedScriptOutputPathFile}"" 2>&1

if %Filesize% lss %MinFileBytes% goto RemoveIt

echo.                                                                           >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo The file is not smaller than the minimmum (%MinFileBytes% bytes). Keep it. >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
goto :EOF


:RemoveIt
echo.                                                                           >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo The file is smaller than the minimmum (%MinFileBytes% bytes). Remove it.   >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo.                                                                           >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo This removes the failed backup file:                                       >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo.                                                                           >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
echo del %FileSpec%                                                             >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
     del %FileSpec%                                                             >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
     if exist %FileSpec% echo   Error: %FileSpec% is still there.               >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
     if not exist %FileSpec% echo     %FileSpec% has been removed.              >> ""{BackupFailedScriptOutputPathFile}"" 2>&1
"
)
                        .Replace("{ProfileFile}", Path.GetFileName(moProfile.sLoadedPathFile))
                        .Replace("{BackupFailedScriptOutputPathFile}", Path.GetFileName(lsBackupFailedScriptOutputPathFile))
                        ;

                // Write the default "backup failed" script if it's
                // not there or if -BackupFailedScriptInit is set.
                if (       !File.Exists(lsBackupFailedScriptPathFile)
                        || moProfile.bValue("-BackupFailedScriptInit", false) )
                {
                    StreamWriter loStreamWriter = null;

                    try
                    {
                        loStreamWriter = new StreamWriter(lsBackupFailedScriptPathFile, false);
                        loStreamWriter.Write(lsBackupFailedScript);

                        // This is used only once then reset.
                        moProfile["-BackupFailedScriptInit"] = false;
                        moProfile.Save();
                    }
                    catch (Exception ex)
                    {
                        this.ShowError(string.Format("File Write Failure: \"{0}\"\r\n"
                                , lsBackupFailedScript) + ex.Message
                                , "Failed Writing File"
                                );
                    }
                    finally
                    {
                        if ( null != loStreamWriter )
                            loStreamWriter.Close();
                    }
                }
            }

            try
            {
                this.LogIt("");
                this.LogIt("Running \"backup failed\" script ...");

                // Cache the arguments to be passed to the script.
                tvProfile  loArgs = new tvProfile();
                                loArgs.Add("-BackupOutputPathFile"          , msCurrentBackupOutputPathFile                                          );
                                loArgs.Add("-BackupOutputFilename"          , Path.GetFileName(msCurrentBackupOutputPathFile)                        );
                                loArgs.Add("-BackupBaseOutputFilename"      , Path.GetFileName(this.sBackupOutputPathFileBase())                     );
                                loArgs.Add("-LocalArchivePath"              , this.sArchivePath()                                                    );
                                loArgs.Add("-VirtualMachineHostArchivePath" , moProfile.sValue("-VirtualMachineHostArchivePath", "")                 );

                                moProfile["-BackupFailedArgs"] = loArgs.sCommandBlock();
                                moProfile.Save();

                // Run the "backup failed" script.
                Process loProcess = new Process();
                        loProcess.StartInfo.FileName = lsBackupFailedScriptPathFile;
                        loProcess.StartInfo.Arguments = string.Format(
                                  " \"{0}\" \"{1}\" \"{2}\" \"{3}\" \"{4}\" \"{5}\" \"{6}\" \"{7}\" \"{8}\" \"{9}\" "
                                , loArgs.sValue("-BackupOutputPathFile"         , "")
                                , loArgs.sValue("-BackupOutputFilename"         , "")
                                , loArgs.sValue("-BackupBaseOutputFilename"     , "")
                                , loArgs.sValue("-LocalArchivePath"             , "")
                                , loArgs.sValue("-VirtualMachineHostArchivePath", "")
                                , ""
                                , ""
                                , ""
                                , ""
                                , ""
                                );
                        loProcess.StartInfo.UseShellExecute = true;
                        loProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                        loProcess.Start();

                // Wait for the "backup failed" script to finish.
                while ( !this.bMainLoopStopped && !loProcess.HasExited )
                {
                    System.Windows.Forms.Application.DoEvents();
                    System.Threading.Thread.Sleep(moProfile.iValue("-MainLoopSleepMS", 100));
                }

                // If a stop request came through, kill the "backup failed" script.
                if ( this.bMainLoopStopped && !this.bKillProcess(loProcess) )
                    this.ShowError("The \"backup failed\" script could not be stopped."
                            , "Backup Failed");

                if ( !this.bMainLoopStopped )
                {
                    if ( 0 == loProcess.ExitCode )
                    {
                        this.LogIt("The \"backup failed\" script finished successfully.");
                    }
                    else
                    {
                        this.LogIt("The \"backup failed\" script did NOT finish successfully.");
                    }
  
                    // Get the output from the "backup failed" script.

                    this.LogIt("\r\nHere's output from the \"backup failed\" script:\r\n\r\n"
                            + this.sFileAsStream(lsBackupFailedScriptOutputPathFile));
                }

                loProcess.Close();
            }
            catch (Exception ex)
            {
                this.SetBackupFailed();
                this.ShowError(ex.Message, "Failed Running \"Backup Failed\" Script");
            }
        }
Example #5
0
        public int iBackupDoneScriptCopyFailuresWithBitField(bool abRerunLastArgs)
        {
            int liBackupDoneScriptCopyFailuresWithBitField = 0;

            // Before the "backup done" script can be initialized,
            // -BackupDoneScriptPathFile and -BackupDoneScriptHelp
            // must be initialized first.
            if ( moProfile.bValue("-BackupDoneScriptInit", false) )
            {
                moProfile.Remove("-BackupDoneScriptPathFile");
                moProfile.Remove("-BackupDoneScriptHelp");
            }

            string lsBackupDoneScriptPathFile = moProfile.sRelativeToProfilePathFile(
                    moProfile.sValue("-BackupDoneScriptPathFile", msBackupDoneScriptPathFileDefault));
            string lsBackupDoneScriptOutputPathFile = lsBackupDoneScriptPathFile + ".txt";

            // If the "backup done" script has not been redefined to point elsewhere,
            // prepare to create it from the current -BackupDoneScriptHelp content.
            // We do this even if the script file actually exists already. This way
            // the following default script will be written to the profile file if
            // it's not already there.
            if ( lsBackupDoneScriptPathFile == moProfile.sRelativeToProfilePathFile(msBackupDoneScriptPathFileDefault) )
            {
                bool    lbUseMainhostArchive    = moProfile.bValue("-UseVirtualMachineHostArchive", false);
                bool    lbUseConnectMainhost    = moProfile.bValue("-UseConnectVirtualMachineHost", false);
                string  lsBackupDoneScript      = moProfile.sValue("-BackupDoneScriptHelp", @"
@echo off
if %1=="""" goto :EOF
::
:: *** ""Backup Done"" script goes here. ***
::
:: This script is executed after each successful backup completes. If you 
:: prompt for input within this DOS script (eg. ""pause""), the script
:: will stay in memory. This is not recommended since such behavior would
:: be similar to a memory leak.
::
:: You can also create and edit another DOS script file and reference that
:: instead (see ""-BackupDoneScriptPathFile"" in ""{ProfileFile}""). You
:: can access several parameters from the completed backup via the DOS shell
:: command-line:
::
:: %1 = ""BackupOutputPathFile""
::
::      This is the full path\file specification of the backup file.
::      It includes the output filename as well as the embedded date.
::
:: %2 = ""BackupOutputFilename""
::
::      This is the backup filename only (ie. no path). It includes the
::      embedded date as well as the filename extension.
::
:: %3 = ""BackupBaseOutputFilename""
::
::      This is the backup filename with no path and no date. It's just
::      the base output filename name with the filename extension.
::
:: %4 = ""LocalArchivePath""
::
::      This is the local archive folder.
::
:: %5 = ""VirtualMachineHostArchive""
::
::      This is the virtual machine host archive share name.
::
:: %6 = ""LogPathFile""
::
::      This is the full path\file specification of the backup log file.
::
::
:: Note: All arguments will be passed with double quotation marks included.
::       So don't use quotes here unless you want ""double double"" quotes.
::       Also, ERRORLEVEL is not reliable enough to be heavily used below.
::
:: The following example copies the backup file to the root of drive C:
:: (if it's ""AdministratorFiles.zip""). Then it outputs a directory listing
:: of the archive folder.
::
:: Example:
::
:: if not %3.==""AdministratorFiles.zip"". goto :EOF
::
::     echo copy %1 C:\  ] ""{BackupDoneScriptOutputPathFile}"" 2>&1
::          copy %1 C:\ ]] ""{BackupDoneScriptOutputPathFile}"" 2>&1
::
:: dir %4               ]] ""{BackupDoneScriptOutputPathFile}"" 2>&1
::
::                      ^^  Replace brackets with darts.

:: The ""CopyFailures"" environment variable is used to keep count of errors to be returned.
set CopyFailures=0

:: Initialize the ""backup done"" script log file. It's for this run only.
echo.                    > ""{BackupDoneScriptOutputPathFile}"" 2>&1
"
+
(!lbUseMainhostArchive ? "" :
@"
:: This references the backup destination copy on the VM host:
set FileSpec=%5\%2

echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo This copies the backup to the virtual machine host archive:            >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo copy %1 %5                                                             >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
     copy %1 %5                                                             >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
     if not exist %FileSpec% echo   Error: %FileSpec% is not there.         >> ""{BackupDoneScriptOutputPathFile}"" 2>&1

     if not exist %FileSpec% set /A CopyFailures += 1
"
)
+
@"
echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo The following copies the backup (base name) to each attached backup    >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo device with the file ""{BackupDriveToken}"" at its root.               >> ""{BackupDoneScriptOutputPathFile}"" 2>&1

set BackupOutputPathFile=%1
set BackupBaseOutputFilename=%3

set BackupDeviceDecimalBitField=0
set BackupDevicePositionExponent=23

:: There are 23 drive letters listed (ie. possible backup devices). A 32-bit integer
:: can handle no more when a corresponding bit field is combined with copy failures.
for %%d in (D: E: F: G: H: I: J: K: L: M: N: O: P: Q: R: S: T: U: V: W: X: Y: Z:) do call :DoCopy %%d

:: Set bit 24 (ie. add 2^23 = 8,388,608) to preserve bit field's leading zeros.
:: Combine the bit field and the copy failures into a single composite value.
:: The factor of 100 means that there can be a maximum of 99 copy failures.

set /A CompositeResult = 100 * (8388608 + %BackupDeviceDecimalBitField%) + %CopyFailures%

echo   CompositeResult=%CompositeResult%                                    >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
exit  %CompositeResult%

:DoCopy
set /A BackupDevicePositionExponent -= 1
dir %1 > nul 2> nul
if ERRORLEVEL 1 goto :EOF
if not exist %1\""{BackupDriveToken}"" goto :EOF

:: Determine the bit position (and the corresponding decimal value) from the exponent.
set BitFieldDevicePosition=1
for /L %%x in (1, 1, %BackupDevicePositionExponent%) do set /A BitFieldDevicePosition *= 2

:: Add the calculated positional value to the bit field for the current backup device.
set /A BackupDeviceDecimalBitField += %BitFieldDevicePosition%


:: This references the backup destination copy on the current backup device (%1):
set FileSpec=%1\%BackupBaseOutputFilename%

echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo This removes the previous backup (if any) from %1                      >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo del %FileSpec%                                                         >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
     del %FileSpec%                                                         >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
     if exist %FileSpec% echo   Error: %FileSpec% is still there.           >> ""{BackupDoneScriptOutputPathFile}"" 2>&1

     if exist %FileSpec% set /A CopyFailures += 1

echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo This copies the current backup to %1                                   >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo.                                                                       >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
echo copy %BackupOutputPathFile% %FileSpec%                                 >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
     copy %BackupOutputPathFile% %FileSpec%                                 >> ""{BackupDoneScriptOutputPathFile}"" 2>&1
     if not exist %FileSpec% echo   Error: %FileSpec% is not there.         >> ""{BackupDoneScriptOutputPathFile}"" 2>&1

     if not exist %FileSpec% set /A CopyFailures += 1
"
)
                        .Replace("{ProfileFile}", Path.GetFileName(moProfile.sLoadedPathFile))
                        .Replace("{BackupDoneScriptOutputPathFile}", Path.GetFileName(lsBackupDoneScriptOutputPathFile))
                        .Replace("{BackupDriveToken}", this.sBackupDriveToken)
                        ;

                // Write the default "backup done" script if it's
                // not there or if -BackupDoneScriptInit is set.
                if (       !File.Exists(lsBackupDoneScriptPathFile)
                        || moProfile.bValue("-BackupDoneScriptInit", false) )
                {
                    StreamWriter loStreamWriter = null;

                    try
                    {
                        loStreamWriter = new StreamWriter(lsBackupDoneScriptPathFile, false);
                        loStreamWriter.Write(lsBackupDoneScript);

                        // This is used only once then reset.
                        moProfile["-BackupDoneScriptInit"] = false;
                        moProfile.Save();
                    }
                    catch (Exception ex)
                    {
                        this.ShowError(string.Format("File Write Failure: \"{0}\"\r\n"
                                , lsBackupDoneScript) + ex.Message
                                , "Failed Writing File"
                                );
                    }
                    finally
                    {
                        if ( null != loStreamWriter )
                            loStreamWriter.Close();
                    }
                }
            }

            try
            {
                this.LogIt("");
                this.LogIt("Running \"backup done\" script ...");

                // Cache the arguments to be passed to the script.
                tvProfile  loArgs = new tvProfile();
                            if ( abRerunLastArgs )
                            {
                                loArgs.LoadFromCommandLine(moProfile.sValue("-BackupDoneArgs", ""), tvProfileLoadActions.Append);
                            }
                            else
                            {
                                loArgs.Add("-BackupOutputPathFile"          , msCurrentBackupOutputPathFile                                          );
                                loArgs.Add("-BackupOutputFilename"          , Path.GetFileName(msCurrentBackupOutputPathFile)                        );
                                loArgs.Add("-BackupBaseOutputFilename"      , Path.GetFileName(this.sBackupOutputPathFileBase())                     );
                                loArgs.Add("-LocalArchivePath"              , this.sArchivePath()                                                    );
                                loArgs.Add("-VirtualMachineHostArchivePath" , moProfile.sValue("-VirtualMachineHostArchivePath", "")                 );
                                loArgs.Add("-LogPathFile"                   , moProfile.sRelativeToProfilePathFile(this.sLogPathFile)                );

                                moProfile["-BackupDoneArgs"] = loArgs.sCommandBlock();
                                moProfile.Save();
                            }

                // Run the "backup done" script.
                Process loProcess = new Process();
                        loProcess.StartInfo.FileName = lsBackupDoneScriptPathFile;
                        loProcess.StartInfo.Arguments = string.Format(
                                  " \"{0}\" \"{1}\" \"{2}\" \"{3}\" \"{4}\" \"{5}\" \"{6}\" \"{7}\" \"{8}\" \"{9}\" "
                                , loArgs.sValue("-BackupOutputPathFile"         , "")
                                , loArgs.sValue("-BackupOutputFilename"         , "")
                                , loArgs.sValue("-BackupBaseOutputFilename"     , "")
                                , loArgs.sValue("-LocalArchivePath"             , "")
                                , loArgs.sValue("-VirtualMachineHostArchivePath", "")
                                , loArgs.sValue("-LogPathFile"                  , "")
                                , ""
                                , ""
                                , ""
                                , ""
                                );
                        loProcess.StartInfo.UseShellExecute = true;
                        loProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                        loProcess.Start();

                // Wait for the "backup done" script to finish.
                while ( !this.bMainLoopStopped && !loProcess.HasExited )
                {
                    System.Windows.Forms.Application.DoEvents();
                    System.Threading.Thread.Sleep(moProfile.iValue("-MainLoopSleepMS", 100));
                }

                // If a stop request came through, kill the "backup done" script.
                if ( this.bMainLoopStopped && !this.bKillProcess(loProcess) )
                    this.ShowError("The \"backup done\" script could not be stopped."
                            , "Backup Failed");

                if ( !this.bMainLoopStopped )
                {
                    // The exit code is defined in the script as a combination of two integers:
                    // a bit field of found backup devices and a count of copy failures (99 max).
                    liBackupDoneScriptCopyFailuresWithBitField = loProcess.ExitCode;

                    double  ldCompositeResult = liBackupDoneScriptCopyFailuresWithBitField / 100.0;
                    int     liCurrentBackupDevicesBitField = (int)ldCompositeResult;   // The integer part is the bit field.

                    // The fractional part (x 100) is the number of copy failures.
                    int liBackupDoneScriptCopyFailures = (int)Math.Round(100 * (ldCompositeResult - liCurrentBackupDevicesBitField));

                    // Compare the bit field of current backup devices to the bit field of devices selected by the user.
                    List<char> loMissingBackupDevices = this.oMissingBackupDevices(liCurrentBackupDevicesBitField);

                    if (0 == liBackupDoneScriptCopyFailures && 0 == loMissingBackupDevices.Count)
                    {
                        this.LogIt("The \"backup done\" script finished successfully.");
                    }
                    else
                    {
                        if ( 0 != liBackupDoneScriptCopyFailures )
                        {
                            this.LogIt(string.Format("The \"backup done\" script had {0} copy failure{1}.\r\n"
                                    , liBackupDoneScriptCopyFailures
                                    , 1 == liBackupDoneScriptCopyFailures ? "" : "s")
                                    );

                            // Get the output from the "backup done" script.

                            string lsFileAsStream = this.sFileAsStream(lsBackupDoneScriptOutputPathFile);

                            this.LogIt("Here's output from the \"backup done\" script:\r\n\r\n" + lsFileAsStream);

                            if ( moProfile.bValue("-ShowBackupDoneScriptErrors", true) )
                                this.DisplayFileAsErrors(lsFileAsStream, "Backup Done Script Errors");
                        }

                        if ( 0 != loMissingBackupDevices.Count )
                            this.LogIt(string.Format("The \"backup done\" script noticed {0} backup device{1} missing.\r\n"
                                    , loMissingBackupDevices.Count
                                    , 1 == loMissingBackupDevices.Count ? "" : "s")
                                    );
                    }
                }

                loProcess.Close();
            }
            catch (Exception ex)
            {
                ++liBackupDoneScriptCopyFailuresWithBitField;
                this.SetBackupFailed();
                this.ShowError(ex.Message, "Failed Running \"Backup Done\" Script");
            }

            return liBackupDoneScriptCopyFailuresWithBitField;
        }
Example #6
0
        /// <summary>
        /// Returns the "BackupOutputPathFile" base name from the given backup set profile.
        /// This is includes everything in the path\file specification except the embedded date.
        /// </summary>
        private string sBackupOutputPathFileBase(tvProfile aoBackupSetProfile)
        {
            string lsBackupOutputPathFileBase = "";

            if ( null != aoBackupSetProfile )
                lsBackupOutputPathFileBase = Path.Combine(this.sArchivePath(aoBackupSetProfile)
                        , aoBackupSetProfile.sValue("-OutputFilename", "Files"))
                        + moProfile.sValue("-BackupOutputExtension", ".zip");

            return lsBackupOutputPathFileBase;
        }
Example #7
0
        private void GetSetConfigurationDefaults()
        {
            tvProfile loBackupSet1Profile = new tvProfile(moProfile.sValue("-BackupSet", "(not set)"));

            if ( !mbGetDefaultsDone )
            {
                try
                {
                    // General
                    this.CleanupFiles.IsChecked = moProfile.bValue("-CleanupFiles", true);
                    this.BackupFiles.IsChecked = moProfile.bValue("-BackupFiles", true);
                    this.BackupBeginScriptEnabled.IsChecked = moProfile.bValue("-BackupBeginScriptEnabled", true);
                    this.BackupDoneScriptEnabled.IsChecked = moProfile.bValue("-BackupDoneScriptEnabled", true);

                    // Step 1
                    this.FolderToBackup.Text = loBackupSet1Profile.sValue("-FolderToBackup",
                            Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));

                    // Step 2
                    this.BackupOutputFilename.Text = loBackupSet1Profile.sValue("-OutputFilename",
                            string.Format("{0}Files", Environment.GetEnvironmentVariable("USERNAME")));

                    this.ArchivePath.Text = moDoGoPcBackup.sArchivePath();

                    this.UseVirtualMachineHostArchive.IsChecked = moProfile.bValue("-UseVirtualMachineHostArchive", false);
                    this.VirtualMachineHostArchivePath.Text = moProfile.sValue("-VirtualMachineHostArchivePath", "");
                    this.UseConnectVirtualMachineHost.IsChecked = moProfile.bValue("-UseConnectVirtualMachineHost", false);
                    this.VirtualMachineHostUsername.Text = moProfile.sValue("-VirtualMachineHostUsername", "");
                    this.VirtualMachineHostPassword.Text = moProfile.sValue("-VirtualMachineHostPassword", "");

                    // Step 3

                    // see below

                    // Step 4
                    this.BackupTime.Text = moProfile.sValue("-BackupTime", "12:00 AM");
                    this.sldBackupTime_ValueFromString(this.BackupTime.Text);
                }
                catch (Exception ex)
                {
                    msGetSetConfigurationDefaultsError = ex.Message;
                }

                mbGetDefaultsDone = true;
            }

            // Step 3

            // If the user merely looks at the backup devices tab, update the profile.
            if ( this.ConfigWizardTabs.SelectedIndex
                    == ItemsControl.ItemsControlFromItemContainer(
                    this.tabStep3).ItemContainerGenerator.IndexFromContainer(this.tabStep3)
                    )
                mbUpdateSelectedBackupDevices = true;

            // The removal or insertion of external devices will be
            // detected whenever the "Setup Wizard" button is clicked.

            if ( 0 == gridBackupDevices.Children.Count )
            {
                string  lsFirstDriveLetter = moDoGoPcBackup.cPossibleDriveLetterBegin.ToString();
                int     liRow = 0;
                int     liColumn = 0;

                // Add each drive (starting with lsFirstDriveLetter) to the list of checkboxes.
                foreach (DriveInfo loDrive in DriveInfo.GetDrives())
                {
                    try
                    {
                        if ( String.Compare(lsFirstDriveLetter, loDrive.Name) < 0 )
                        {
                            CheckBox    loCheckBox = new CheckBox();
                                        loCheckBox.Width = 200;
                                        loCheckBox.Tag = loDrive;

                            // If the drive has a valid volume label, display it alongside the drive name.
                            try
                            {
                                loCheckBox.Content = "(" + loDrive.Name.Substring(0, 2) + ") " + loDrive.VolumeLabel;
                            }
                            // Otherwise, display the drive name by itself.
                            catch
                            {
                                loCheckBox.Content = "(" + loDrive.Name.Substring(0, 2) + ") ";
                            }

                            // Add a CheckBox to the tab to represent the drive.
                            gridBackupDevices.Children.Add(loCheckBox);
                            Grid.SetRow(loCheckBox, liRow);
                            Grid.SetColumn(loCheckBox, liColumn);

                            // Arrange the CheckBoxes such that a new column is formed for every 8 CheckBoxes.
                            if ( liRow < 7 )
                            {
                                ++liRow;
                            }
                            else
                            {
                                liRow = 0;
                                ++liColumn;
                            }

                            string lsTokenPathFile = Path.Combine((loCheckBox.Tag as DriveInfo).Name, moDoGoPcBackup.sBackupDriveToken);

                            try
                            {
                                File.Create(lsTokenPathFile + ".test").Close();
                                File.Delete(lsTokenPathFile + ".test");
                                loCheckBox.Foreground = Brushes.DarkGreen;
                            }
                            catch
                            {
                                loCheckBox.Foreground = Brushes.Red;
                                loCheckBox.IsEnabled = false;
                            }

                            // If the BackupDriveToken is already on a drive, set the drive's CheckBox to 'checked.'
                            if ( File.Exists(lsTokenPathFile) )
                                loCheckBox.IsChecked = true;

                            // Create or delete the BackupDriveToken from the drive whenever it is checked or unchecked.
                            loCheckBox.Checked += new RoutedEventHandler(BackupDeviceCheckboxStateChanged);
                            loCheckBox.Unchecked += new RoutedEventHandler(BackupDeviceCheckboxStateChanged);
                        }
                    }
                    catch {}
                }
            }

            // Finish
            this.ReviewFolderToBackup.Text = this.FolderToBackup.Text;
            this.ReviewOutputFilename.Text = this.BackupOutputFilename.Text;
            this.ReviewArchivePath.Text = this.ArchivePath.Text;
            this.ReviewBackupTime.Text = this.BackupTime.Text;

            tvProfile loSelectedBackupDevices = new tvProfile();
            string lsSelectedDrives = "";

            // Generate a string with the content of each CheckBox that the user checked in Step 4.
            foreach (CheckBox loCheckBox in gridBackupDevices.Children)
            {
                if ((bool)loCheckBox.IsChecked)
                {
                    loSelectedBackupDevices.Add("-Device", loSelectedBackupDevices.sSwapHyphens(loCheckBox.Content.ToString()));
                    lsSelectedDrives += loCheckBox.Content.ToString().Substring(0, 5);
                }
            }

            this.ReviewAdditionalDevices.Text = lsSelectedDrives;

            loBackupSet1Profile["-FolderToBackup"] = this.ReviewFolderToBackup.Text;
            loBackupSet1Profile["-OutputFilename"] = this.ReviewOutputFilename.Text;

            if ( null == msGetSetConfigurationDefaultsError )
            {
                moProfile["-BackupSet"] = loBackupSet1Profile.sCommandBlock();
                moProfile["-ArchivePath"] = this.ReviewArchivePath.Text;
                moProfile["-BackupTime"] = this.ReviewBackupTime.Text;

                moProfile["-UseVirtualMachineHostArchive"] = this.UseVirtualMachineHostArchive.IsChecked;
                moProfile["-VirtualMachineHostArchivePath"] = this.VirtualMachineHostArchivePath.Text;
                moProfile["-UseConnectVirtualMachineHost"] = this.UseConnectVirtualMachineHost.IsChecked;
                moProfile["-VirtualMachineHostUsername"] = this.VirtualMachineHostUsername.Text;
                moProfile["-VirtualMachineHostPassword"] = this.VirtualMachineHostPassword.Text;

                // Only update the selected backup devices list (and bit field) if the backup devices
                // tab has been viewed or one of the backup device checkboxes has been clicked.
                if ( mbUpdateSelectedBackupDevices )
                {
                    // Make the list of selected backup devices a multi-line block by inserting newlines before hyphens.
                    moProfile["-SelectedBackupDevices"] = loSelectedBackupDevices.sCommandBlock();
                    moProfile["-SelectedBackupDevicesBitField"] = Convert.ToString(this.iSelectedBackupDevicesBitField(), 2);

                    mbUpdateSelectedBackupDevices = false;
                }

                moProfile["-CleanupFiles"] = this.CleanupFiles.IsChecked;
                moProfile["-BackupFiles"] = this.BackupFiles.IsChecked;
                moProfile["-BackupBeginScriptEnabled"] = this.BackupBeginScriptEnabled.IsChecked;
                moProfile["-BackupDoneScriptEnabled"] = this.BackupDoneScriptEnabled.IsChecked;

                moProfile.Save();
            }

            // Reset the loop timer only if the backup time was changed in the configuration.
            if ( !this.bMainLoopStopped && this.BackupTime.Text != msPreviousBackupTime )
            {
                msPreviousBackupTime = this.BackupTime.Text;
                mdtNextStart = DateTime.MinValue;
                this.bMainLoopRestart = true;
            }
        }