Beispiel #1
0
        private string msPreviousBackupTime = null; // This tracks changes to backup time configuration.

        #endregion Fields

        #region Constructors

        /// <summary>
        /// This constructor expects a file backup 
        /// application object to be provided.
        /// </summary>
        /// <param name="aoDoGoPcBackup">
        /// The given file backup object creates dated archives
        /// of file collections from the local file system.
        /// </param>
        public UI(DoGoPcBackup aoDoGoPcBackup)
        {
            InitializeComponent();

            // This loads window UI defaults from the given profile.
            base.Init();

            moProfile = aoDoGoPcBackup.oProfile;
            moDoGoPcBackup = aoDoGoPcBackup;
        }
        static void Main(string[] args)
        {
            DoGoPcBackup loMain  = null;

            try
            {
                tvProfile   loProfile = new tvProfile(args);
                bool        lbFirstInstance;
                            Mutex loMutex = new Mutex(false, "Global\\" + Application.ResourceAssembly.GetName().Name, out lbFirstInstance);
                            if ( !lbFirstInstance )
                                DoGoPcBackup.ActivateAlreadyRunningInstance(args, loProfile);

                if ( lbFirstInstance && !loProfile.bExit )
                {
                    loProfile.GetAdd("-Help",
                            @"
Introduction


This utility performs file backups and file cleanups in the background.

It also acts as its own scheduler. First, it checks for files to be removed on
a given schedule. Then it runs a backup of your files automatically.

There is no need to use a job scheduler unless this software is running on a 
server computer that has no regular user activity (see -NoPrompts and -RunOnce
below).

You provide various file specifications (ie. locations of the files to backup
and to cleanup) as well as file age limits for the files to cleanup. The rest
is automatic.

This utility will run in the background unless its timer is turned off. Its
simple user interface (UI) is usually minimized to the system tray.


Command-Line Usage


Open this utility's profile file to see additional options available. It is
usually located in the same folder as ""{EXE}"" and has the same name
with "".txt"" added (see ""{INI}"").

Profile file options can be overridden with command-line arguments. The
keys for any ""-key=value"" pairs passed on the command-line must match
those that appear in the profile (with the exception of the ""-ini"" key).

For example, the following invokes the use of an alternative profile file:

    {EXE} -ini=NewProfile.txt

This tells the software to run in automatic mode:

    {EXE} -AutoStart


Author:  George Schiro ([email protected])

Date:    7/3/2013




Options and Features


The main options for this utility are listed below with their default values.
A brief description of each feature follows.

-AddTasks= NO DEFAULT VALUE

    Each added task has its own profile:

    -Task= NO DEFAULT VALUE

        -CommandEXE= NO DEFAULT VALUE

            This is the path\file specification of the task executable to be run.

        -CommandArgs=""""

            This is the list of arguments passed to the task executable.

        -CommandWindowTitle=""""

            This is the main window title for this instance of the task executable.
            This will be used to determine, during startup, if the task is already
            running (when multiple instances of the same executable are found).

        -CreateNoWindow=False

            Set this switch True and nothing will be displayed when the task runs.

        -OnStartup=False

            Set this switch True and the task will start each time ""{EXE}""
            starts. If the task EXE is already running, it will not be started again.

        -StartTime= NO DEFAULT VALUE

            Set this to the time of day to run the task (eg. 3:00am, 9:30pm, etc).

        -StartDays=""""

            Set this to days of the week to run the task (eg. Monday, Friday, etc).
            This value may include a comma-separated list of days as well as ranges
            of days. Leave this blank and the task will run every day at -StartTime.

        -TimeoutMinutes=0

            Set this to a number greater than zero to have the task run to completion
            and have all output properly logged before proceeding to the next task
            (ie. -CreateNoWindow will be set and IO redirection will be handled).

        -UnloadOnExit=False

            Set this switch True and the task executable will be removed from memory
            (if it's still running) when ""{EXE}"" exits.


        Here's an example:

        -AddTasks=[

            -Task= -OnStartup -CommandEXE=http://xkcd.com
            -Task= -StartTime=6:00am -CommandEXE=shutdown.exe -CommandArgs=/r /t 60
            -Task= -StartTime=7:00am -StartDays=""Mon-Wed,Friday,Saturday"" -CommandEXE=""C:\Program Files\Calibre2\calibre.exe""  -Note=Fetch NY Times after 6:30am
            -Task= -StartTime=8:00am -StartDays=""Sunday"" -CommandEXE=""C:\Program Files\Calibre2\calibre.exe""  -Note=Fetch NY Times after 7:30am Sundays

        -AddTasks=]

-ArchivePath=C:\Archive

    This is the destination folder of the backup output files unless
    overridden in -BackupSet (see below).

-AutoStart=True

    This tells the software to run in automatic mode. Set this switch False
    and the main loop in the UI will only start manually. The software will
    also vacate memory after the UI window closes. This is the timer switch.

-BackupBeginScriptEnabled=True

    Set this switch False to skip running the ""backup begin"" script.

-BackupBeginScriptHelp= SEE PROFILE FOR DEFAULT VALUE

    This is the default content of the DOS script that is initially written to
    -BackupBeginScriptPathFile and run before each backup starts. It contains
    a description of the command-line arguments passed to the script at runtime.

-BackupBeginScriptInit=False

    Set this switch True and the ""backup begin"" script will be automatically
    overwritten from the content of -BackupBeginScriptHelp. Once used this switch
    will be reset to False.

    Note: the content of -BackupBeginScriptHelp will also be overwritten from the
    default value embedded in the executable file.

-BackupBeginScriptPathFile=GoPcBackupBegin.cmd

    This DOS shell script is run before each backup starts. Edit the contents
    of the file or point this parameter to another file. If you delete the file,
    it will be recreated from the content found in -BackupBeginScriptHelp (see 
    above).

-BackupDoneScriptEnabled=True

    Set this switch False to skip running the ""backup done"" script.

-BackupDoneScriptHelp= SEE PROFILE FOR DEFAULT VALUE

    This is the default content of the DOS script that is initially written to
    -BackupDoneScriptPathFile and run after each successful backup. It contains
    a description of the command-line arguments passed to the script at runtime.

-BackupDoneScriptInit=False

    Set this switch True and the ""backup done"" script will be automatically
    overwritten from the content of -BackupDoneScriptHelp. Once used this switch
    will be reset to False.

    Note: the content of -BackupDoneScriptHelp will also be overwritten from the
    default value embedded in the executable file.

-BackupDoneScriptPathFile=GoPcBackupDone.cmd

    This DOS shell script is run after each successful backup completes. You 
    can edit the contents of the file or point this parameter to another file.
    If you delete the file, it will be recreated from the content found in 
    -BackupDoneScriptHelp (see above).

-BackupFailedScriptEnabled=True

    Set this switch False to skip running the ""backup failed"" script.

-BackupFailedScriptHelp= SEE PROFILE FOR DEFAULT VALUE

    This is the default content of the DOS script that is initially written to
    -BackupFailedScriptPathFile and run after each failed backup. It contains
    a description of the command-line arguments passed to the script at runtime.

-BackupFailedScriptInit=False

    Set this switch True and the ""backup failed"" script will be automatically
    overwritten from the content of -BackupFailedScriptHelp. Once used this switch
    will be reset to False.

    Note: the content of -BackupFailedScriptHelp will also be overwritten from the
    default value embedded in the executable file.

-BackupFailedScriptPathFile=GoPcBackupFailed.cmd

    This DOS shell script is run after a backup fails to complete. You can
    edit the contents of the file or point this parameter to another file.
    If you delete the file, it will be recreated from the content found in 
    -BackupFailedScriptHelp (see above).

-BackupDriveToken=(This is my GoPC backup drive.)

    This is the filename looked for at the root of every storage device attached
    to the computer. If found, a copy of the backup will be written there.

-BackupFileSpec=*

    This wildcard is appended to folders to backup (see -FolderToBackup).

-BackupFiles=True

    Set this switch False to disable backups (ie. do file cleanups only).

-BackupOutputExtension=.zip

    This is appended to all backup path\filenames (see -OutputFilename below).

-BackupOutputFilenameDateFormat=-yyyy-MM-dd

    This format string is used to form the variable part of each backup
    output filename. It is inserted between the filename and the extension
    (see -OutputFilename below and -BackupOutputExtension above).

-BackupSet=""One of many file sets to backup goes here.""

    Each file backup set has its own profile:

        -ArchivePath= INHERITED

            This is the destination folder of the backup output files. If
            provided, this value will override the parent -ArchivePath (see
            above).

        -BackupFileSpec= INHERITED

            This wildcard is appended to each folder to backup. If provided,
            it will override the parent -BackupFileSpec (see above).

        -FolderToBackup=""One of many folders to backup goes here.""

            This is the full path\file specification of a folder to backup.
            This parameter can appear multiple times in each backup set.

            Instead of an entire folder you can use a path\file pattern like
            ""C:\Folder\File?.*"" to backup a subset of files or a single file.

        -OutputFilename=Files

            This is the backup output filename with no path and no extension.
            This parameter will be combined with -BackupOutputExtension, 
            -ArchivePath and -BackupOutputFilenameDateFormat to produce a
            full backup output path\file specification.

-BackupTime=12:00 AM

    This is the time each day that the backup starts.

-BackupTimeMinsPerTick=15

    This determines how many minutes the backup time changes with each tick
    of the backup time selection slider in the UI.

-CleanupFiles=True

    Set this switch False to disable cleanups (ie. do file backups only).

-CleanupLoopSleepMS=1

    This is the number of milliseconds of process thread sleep time between
    file deletions. The default of 1 ms should result in rapid deletions. You 
    can increase this value if you are concerned that the UI is not responsive
    enough or the process is using too much CPU while deleting.

-CleanupSet=""One of many file sets to cleanup goes here.""

    Each file cleanup set has its own profile:

        -AgeDays=365000

            This is the maximum file age in days. It is 1000 years by default.
            Only files older than this will be considered for deletion.

        -ApplyDeletionLimit=True

            Set this switch False and the cleanup process won't limit deletions
            to files regularly replaced by newer files. Without such a limit
            a large collection of very old files may be wiped out in one run.
            With the limit in place an old file will be removed only if a newer
            file exists to replace it.

            In other words, with this switch set, there should always be as many
            files retained as there are days in ""-AgeDays"" multiplied by the
            frequency of backups (1440 divided by -MainLoopMinutes, see below).

        -CleanupHidden=False

            Set this switch True and the file cleanup process will include
            hidden files as well. If -Recurse is also True (see below), hidden
            folders will also be removed.

        -CleanupReadOnly=False

            Set this switch True and the file cleanup process will include
            read-only files as well. If -Recurse is also True (see below), 
            read-only folders will also be removed.

        -DeletedFileListDateTimeType=LastWriteTime

            Each file has 3 timestamps: CreationTime, LastAccessTime
            and LastWriteTime.

            The default (""LastWriteTime"") is the file modification date.

        -FilesToDelete=""One of many path\file specifications goes here.""

            These are the files evaluated for deletion based on their age
            (see -AgeDays above). Wildcards are expected but not required
            (you can reference a single file if you like).

        -Recurse=False

            Set this switch True and the file cleanup process will recurse 
            through all subdirectories starting from the path of the given
            -FilesToDelete (see above) looking for files to remove with the
            same file specification found in the -FilesToDelete parameter.

        -RecurseFolder=""""

            This identifies subfolders found within the folder defined by
            -FilesToDelete (see above). These subfolders can occur at any
            level of the directory hierarchy above the path provided in
            -FilesToDelete. If -RecurseFolder is non-empty, only files found
            within the -FilesToDelete path and also within any subfolder
            (from the given path upward) with the given subfolder name will
            be evaluated for removal.

            This parameter has the effect of greatly limiting the recursion.

            BE CAREFUL! If you don't provide this parameter or you specify
            an empty value, all files matching the file specification in the
            given -FilesToDelete at every level of the directory structure
            (starting at the path found in -FilesToDelete) will be evaluated
            for removal.

            IMPORTANT! Every empty folder found within the given recursive
            subfolder (at any level above the starting path) will also be
            removed.


        Here's a single line example:

        -CleanupSet= -AgeDays=90 -FilesToDelete=C:\WINDOWS\TEMP\*.*


        Here's a multi-line example:

        -CleanupSet=[

            -AgeDays=60
            -FilesToDelete=C:\WINDOWS\TEMP\*.*
            -FilesToDelete=C:\WINDOWS\system32\*.log
            -FilesToDelete=C:\WINDOWS\system32\LogFiles\W3SVC1\*.log
            -FilesToDelete=C:\Documents and Settings\Administrator\Local Settings\Temp\*.*
            -FilesToDelete=C:\Program Files\GoPcBackup\GoPcBackupList*.txt

        -CleanupSet=]
        -CleanupSet=[

            -AgeDays=14
            -FilesToDelete=C:\Documents and Settings\*.*
            -CleanupHidden
            -CleanupReadOnly
            -Recurse
            -RecurseFolder=Local Settings\Temp

        -CleanupSet=]
        -CleanupSet=[

            -AgeDays=90
            -FilesToDelete=C:\Archive\*.*

        -CleanupSet=]

-DeletedFileListDateFormat=-yyyy-MM-dd

    This format string is used to form the variable part of each deleted file
    list output filename (see -DeletedFileListOutputPathFile below). It is 
    inserted between the filename and the extension.

-DeletedFileListOutputColumnFormat={0, -22:MM-dd-yyyy hh:mm:ss tt}  {1, 13:#,#}  {2}

    This format string specifies the layout of the three file attribute output 
    columns (last modified date, file size and path\file name, resp.) for each
    file in the deleted file list (see -DeletedFileListOutputPathFile below).

-DeletedFileListOutputColumnHeaderArray=Deleted File Time,File Size,Former File Location

    This array of names specifies the column headers of the deleted file list
    (see -DeletedFileListOutputPathFile below).

-DeletedFileListOutputHeader={0, -10:MM-dd-yyyy} File Cleanup List

    This format string specifies the layout of the deleted file list output file
    header (see -DeletedFileListOutputPathFile below).

-DeletedFileListOutputPathFile=Logs\DeletedFileList.txt

    This is the output path\file that will contain the list of deleted files.
    The profile file name will be prepended to the default and the current date
    (see -DeletedFileListDateFormat) will be inserted between the filename and 
    the extension.

-FetchSource=False

    Set this switch True to fetch the source code for this utility from the EXE.
    Look in the containing folder for a ZIP file with the full project sources.

-Help= SEE PROFILE FOR DEFAULT VALUE

    This help text.

-KillProcessOrderlyWaitSecs=30

    This is the maximum number of seconds given to a process after a ""close""
    command is given before the process is forcibly terminated.

-KillProcessForcedWaitMS=1000

    This is the maximum milliseconds to wait while force killing a process.

-LogEntryDateTimeFormatPrefix""yyyy-MM-dd hh:mm:ss:fff tt  ""

    This format string is used to prepend a timestamp prefix to each log entry in
    the process log file (see -LogPathFile below).    

-LogFileDateFormat=-yyyy-MM-dd

    This format string is used to form the variable part of each backup / cleanup
    log file output filename (see -LogPathFile below). It is inserted between the
    filename and the extension.

-LogPathFile=Logs\Log.txt

    This is the output path\file that will contain the backup / cleanup process
    log. The profile file name will be prepended to the default and the current
    date (see -LogFileDateFormat above) will be inserted between the filename 
    and the extension.

-MainLoopMinutes=1440

    This is the number of minutes until the next run. One day is the default.

-MainLoopSleepMS=100

    This is the number of milliseconds of process thread sleep wait time between
    loops. The default of 100 ms should be a happy medium between a responsive
    overall UI and a responsive process timer UI. You can increase this value
    if you are concerned that the timer UI is using too much CPU while waiting.

-NoPrompts=False

    Set this switch True and all pop-up prompts will be suppressed. Messages
    are written to the log instead (see -LogPathFile above). You must use this
    switch whenever the software is run via a server computer batch job or job
    scheduler (ie. where no user interaction is permitted).

-PreviousBackupDevicesMissing=False

    This is the True or False ""Devices Missing"" status of the previous backup 
    run. If True, at least one external device was missing when the backup ran.

-PreviousBackupOk= NO DEFAULT VALUE

    This is the True or False ""Ok"" status of the previous backup / cleanup run.

-PreviousBackupTime= NO DEFAULT VALUE

    This is the completion timestamp of the previous backup / cleanup run.

-RunOnce=False

    Set this switch True to run this utility one time only (with no UI) then
    shutdown automatically thereafter. This switch is useful if the utility
    is run in a batch process or if it is run by a server job scheduler.

-SaveProfile=True

    Set this switch False to prevent saving to the profile file by the backup
    software itself. This is not recommended since backup status information is 
    written to the profile after each backup runs.

-SelectedBackupDevices= NO DEFAULT VALUE

    This is the list of selected backup devices as human readable text.

-SelectedBackupDevicesBitField=0 (0 means not yet set)

    This is the list of selected backup devices as a bit field. All bit fields
    have a leading 1 bit to preserve leading zeros. The second bit starts the
    device list (ie. drive letter list). Drive C: is not available as a backup
    device. So the second bit identifies drive D:.

-ShowBackupBeginScriptErrors=True

    Set this switch False to suppress the pop-up display of ""backup begin"" script
    errors (see -BackupBeginScriptPathFile above).

-ShowBackupDoneScriptErrors=True

    Set this switch False to suppress the pop-up display of ""backup done"" script
    errors (see -BackupDoneScriptPathFile above).

-ShowDeletedFileList=False

    Set this switch True and the list of deleted files will be displayed in a 
    pop-up window.

-ShowProfile=False

    Set this switch True to immediately display the entire contents of the profile
    file at startup in command-line format. This is sometimes helpful to diagnose
    problems.

-UseConnectVirtualMachineHost=False

    Set this switch True to force a connection to the virtual machine share archive
    before each backup starts (ie. during the ""backup begin"" script).

-UseVirtualMachineHostArchive=False

    Set this switch True and code will be added to the ""backup done"" script
    (see -BackupDoneScriptPathFile above) to copy backups to your virtual
    machine host computer (assuming you have one). Alternatively, any network
    share can be referenced here for a similar purpose.

-VirtualMachineHostArchivePath= NO DEFAULT VALUE

    This value is used within the ""backup done"" script to copy backups to the
    virtual machine host share (see -UseVirtualMachineHostArchive above).

    You may want to reference your VM host by IP address rather than by name.
    Doing so is often more reliable than using net bios names on your local
    area network.

-VirtualMachineHostPassword= NO DEFAULT VALUE

    This value is the password used within the ""backup begin"" script to log
    into the virtual machine host share (see -UseConnectVirtualMachineHost
    above).

-VirtualMachineHostUsername= NO DEFAULT VALUE

    This value is the username used within the ""backup begin"" script to log
    into the virtual machine host share (see -UseConnectVirtualMachineHost
    above).

-XML_Profile=False

    Set this switch True to change the profile file from command-line format
    to XML format.

-ZipToolEXE=7z.exe

    This is the ZIP tool executable that performs the backup compression.

-ZipToolEXEargs=a -ssw ""{{BackupOutputPathFile}}"" @""{{BackupPathFiles}}"" -w""{{BackupOutputPath}}""

    These are command-line arguments passed to the ZIP compression tool (see
    -ZipToolEXE above). The tokens (in curly brackets) are self-evident. They
    are replaced at runtime.

-ZipToolEXEargsMore= NO DEFAULT VALUE

    These are additional command line arguments for the ZIP tool. Using
    this parameter makes it easier to add functionality without changing
    the existing command line. A typical example would be to supply an 
    encryption password on the command line to ""{EXE}"" itself.

-ZipToolFileListFileDateFormat=-yyyy-MM-dd

    This format string is used to form the variable part of each file list
    output filename (see -ZipToolFileListPathFile below). It is inserted
    between the filename and the extension.

-ZipToolFileListPathFile=FileLists\ZipFileList.txt

    This is the file used to store the list of filenames to be compressed.
    The profile file name will be prepended to the default and the current
    date (see -ZipToolFileListFileDateFormat above) will be inserted (with
    a GUID) between the filename and the extension.

-ZipToolLastRunCmdPathFile=Run Last Backup.cmd

    This is a script file (text), which contains a copy of the last ZIP tool
    command line executed.


Notes:

    There may be various other settings that can be adjusted also (user
    interface settings, etc). See the profile file (""{INI}"")
    for all available options.

    To see the options related to any particular behavior, you must run that
    part of the software first. Configuration options are added ""on the fly""
    (in order of execution) to ""{INI}"" as the software runs.

"
                            .Replace("{EXE}", Path.GetFileName(Application.ResourceAssembly.Location))
                            .Replace("{INI}", Path.GetFileName(loProfile.sActualPathFile))
                            .Replace("{{", "{")
                            .Replace("}}", "}")
                            );

                    // Fetch simple setup.
                    tvFetchResource.ToDisk(Application.ResourceAssembly.GetName().Name
                            , "Setup Application Folder.exe", null);

                    // Fetch source code.
                    if ( loProfile.bValue("-FetchSource", false) )
                        tvFetchResource.ToDisk(Application.ResourceAssembly.GetName().Name
                                , Application.ResourceAssembly.GetName().Name + ".zip", null);


                    // Updates start here.
                    if ( loProfile.bFileJustCreated )
                    {
                        loProfile["-Updated20160416"] = true;
                        loProfile.Save();
                    }
                    else
                    {
                        if ( !loProfile.bValue("-Updated20160416", false) )
                        {
                            //if ( MessageBoxResult.Cancel == MessageBox.Show(
                            //          "This software has been updated."
                            //        + " It requires a change to your -ZipToolEXEargs."
                            //        + "Shall we remove the old -ZipToolEXEargs now?"
                            //        , Application.ResourceAssembly.GetName().Name
                            //        , MessageBoxButton.OKCancel, MessageBoxImage.Question) )
                            //{
                            //    loProfile.bExit = true;
                            //}
                            //else
                            //{
                                loProfile.Remove("-ZipToolEXEargs");

                                loProfile["-Updated20160416"] = true;
                                loProfile.Save();
                            //}
                        }
                    }
                    // Updates end here.


                    if ( !loProfile.bExit )
                    {
                        if ( loProfile.bValue("-RunOnce", false) )
                        {
                            // Run in batch mode.

                            // Turns off the "loading" message.
                            loProfile.bAppFullyLoaded = true;

                            DoGoPcBackup    loDoDa = new DoGoPcBackup(loProfile);
                                            loDoDa.CleanupFiles();
                                            loDoDa.BackupFiles();
                        }
                        else
                        {
                            // Run in interactive mode.

                            try
                            {
                                loMain = new DoGoPcBackup(loProfile);

                                // Load the UI.
                                UI  loUI = new UI(loMain);
                                    loMain.oUI = loUI;

                                loMain.Run(loUI);
                            }
                            catch (ObjectDisposedException) {}
                        }

                        GC.KeepAlive(loMutex);
                    }
                }
            }
            catch (SecurityException)
            {
                tvFetchResource.NetworkSecurityStartupErrorMessage();
            }
            catch (Exception ex)
            {
                tvFetchResource.ErrorMessage(null, ex.Message);
            }
            finally
            {
                if ( null != loMain && null != loMain.oUI )
                    loMain.oUI.Close();
            }
        }
        public static void ActivateAlreadyRunningInstance(string[] args, tvProfile aoProfile)
        {
            if ( 0 == args.Length )
            {
                // This activates a previous instance before exiting.
                PostMessage((IntPtr)HWND_BROADCAST, WM_SHOWME, IntPtr.Zero, IntPtr.Zero);
            }
            else
            {
                tvProfile loProfile = null;

                if ( null != aoProfile.sLoadedPathFile )
                {
                    loProfile = aoProfile;
                }
                else
                {
                    aoProfile.bAppFullyLoaded = true;   // Turns off the "loading" message.

                    // The default profile was likely attempted but failed to load
                    // (due to contention). Try loading the backup profile instead.

                    string  lsPath = Path.GetDirectoryName(aoProfile.sDefaultPathFile);
                    string  lsFilename = Path.GetFileName(aoProfile.sDefaultPathFile);
                    string  lsExt = Path.GetExtension(aoProfile.sDefaultPathFile);
                    string  lsBackupPathFile = Path.Combine(lsPath, lsFilename) + ".backup" + lsExt;

                    loProfile = new tvProfile(lsBackupPathFile, tvProfileFileCreateActions.NoFileCreate);
                    loProfile.LoadFromCommandLineArray(args, tvProfileLoadActions.Merge);
                }

                // Arguments were passed, so start a new "-RunOnce" instance.
                loProfile.LoadFromCommandLine("-ActivateAlreadyRunningInstance -RunOnce", tvProfileLoadActions.Merge);
                loProfile.bAppFullyLoaded = true;   // Turns off the "loading" message.

                DoGoPcBackup    loDoDa = new DoGoPcBackup(loProfile);
                                loDoDa.CleanupFiles();
                                loDoDa.BackupFiles();
            }
        }