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");
            }
        }
        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;
        }
        /// <summary>
        /// Returns a subset of the profile as a new profile. All items
        /// that match asKey will be included.
        /// </summary>
        /// <param name="asKey">
        /// The key string used to find items in the profile. "*" or a regular
        /// expression may be included.
        /// </param>
        /// <param name="abRemoveKeyPrefix">
        /// If true and asKey contains "*" or ".*", asKey (sans the wildcards)
        /// will be removed from each key prior to its addition to the new
        /// profile.
        /// </param>
        /// <returns>
        /// A new profile object containing the items found.
        /// </returns>
        public tvProfile oOneKeyProfile(String asKey, bool abRemoveKeyPrefix)
        {
            String  lsKeyPrefixToRemove = asKey.Replace(".*","").Replace("*","");
                    if ( asKey == lsKeyPrefixToRemove || "" == lsKeyPrefixToRemove )
                    {
                        // If the given key contains no wildcards, it's not really a prefix.
                        abRemoveKeyPrefix = false;
                    }
            tvProfile loProfile = new tvProfile();

            if ( mbUseLiteralsOnly )
            {
                foreach ( DictionaryEntry loEntry in this )
                {
                    String lsKey = loEntry.Key.ToString();

                    if ( lsKey == asKey )
                    {
                        if ( abRemoveKeyPrefix )
                        {
                            loProfile.Add("-" + lsKey.Replace(lsKeyPrefixToRemove, ""), loEntry.Value);
                        }
                        else
                        {
                            loProfile.Add(lsKey, loEntry.Value);
                        }
                    }
                }
            }
            else
            {
                foreach ( DictionaryEntry loEntry in this )
                {
                    String lsKey = loEntry.Key.ToString();

                    if ( Regex.IsMatch(lsKey, this.sExpression(asKey), RegexOptions.IgnoreCase) )
                    {
                        if ( abRemoveKeyPrefix )
                        {
                            loProfile.Add("-" + lsKey.Replace(lsKeyPrefixToRemove, ""), loEntry.Value);
                        }
                        else
                        {
                            loProfile.Add(lsKey, loEntry.Value);
                        }
                    }
                }
            }

            return loProfile;
        }
        private void ReplaceDefaultProfileFromCommandLine(String[] asCommandLineArray)
        {
            this.LoadFromCommandLineArray(asCommandLineArray, tvProfileLoadActions.Overwrite);

            String[] lsIniKeys = new String[] { "-ini", "-ProfileFile" };

            int     liIniKeyIndex = - 1;
                    if (      this.ContainsKey(lsIniKeys[0]) )
                    {
                        liIniKeyIndex = 0;
                    }
                    else if ( this.ContainsKey(lsIniKeys[1]) )
                    {
                        liIniKeyIndex = 1;
                    }
            String  lsProfilePathFile = null;
                    if ( -1 != liIniKeyIndex )
                    {
                        lsProfilePathFile = this.sValue(lsIniKeys[liIniKeyIndex], "");
                    }
            bool    lbFirstArgIsFile = false;
            String  lsFirstArg = null;
                    try
                    {
                        if ( -1 != this.sInputCommandLineArray[0].IndexOf(".vshost.")
                                || this.sInputCommandLineArray[0] == this.sExePathFile )
                        {
                            lsFirstArg = this.sInputCommandLineArray[1];
                        }
                        else
                        {
                            lsFirstArg = this.sInputCommandLineArray[0];
                        }
                    }
                    catch {}

            if ( null != lsFirstArg
                    && File.Exists(this.sRelativeToProfilePathFile(lsFirstArg)) )
            {
                if ( null != lsProfilePathFile )
                {
                    // If the first argument passed on the command line is actually
                    // a file (that exists) and if an -ini key was also provided, then
                    // add the file reference to the profile using the "-File" key.
                    lbFirstArgIsFile = true;
                }
                else
                {
                    // If no -ini key was passed, then assume the referenced file is
                    // actually a profile file to be loaded.
                    lsProfilePathFile = lsFirstArg;
                }
            }

            if ( null != lsProfilePathFile )
            {
                // Load the referenced profile file.
                tvProfile   loNewProfile = new tvProfile();
                            loNewProfile.eFileCreateAction = this.eFileCreateAction;
                            loNewProfile.bUseXmlFiles = this.bUseXmlFiles;
                            loNewProfile.bAddStandardDefaults = this.bAddStandardDefaults;
                            loNewProfile.Load(lsProfilePathFile, tvProfileLoadActions.Overwrite);

                            this.sActualPathFile = loNewProfile.sActualPathFile;
                            this.sLoadedPathFile = loNewProfile.sLoadedPathFile;
                            this.bExit = loNewProfile.bExit;

                if ( !this.bExit )
                {
                    this.bFileJustCreated = loNewProfile.bFileJustCreated;

                    // We now need a slightly modified version of the given command line
                    // (ie. sans the -ini key but with a -File key, if appropriate).
                    tvProfile   loCommandLine = new tvProfile();
                                loCommandLine.LoadFromCommandLineArray(
                                        this.sInputCommandLineArray, tvProfileLoadActions.Overwrite);
                                if ( -1 != liIniKeyIndex )
                                    loCommandLine.Remove(lsIniKeys[liIniKeyIndex]);
                                if ( lbFirstArgIsFile )
                                    loCommandLine.Add("-File", lsFirstArg);

                    // Now merge in the original command line (with the above
                    // adjustments). Command line items take precedence over file items.
                    loNewProfile.LoadFromCommandLineArray(loCommandLine.sCommandLineArray(), tvProfileLoadActions.Merge);
                    this.bSaveEnabled = loNewProfile.bSaveEnabled;

                    // Reinitiallize the profile with the new combined results.
                    this.LoadFromCommandLineArray(loNewProfile.sCommandLineArray(), tvProfileLoadActions.Overwrite);
                    this.bDefaultFileReplaced = true;
                }

                loNewProfile.UnlockProfileFile();
            }
        }
Exemple #5
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;
            }
        }