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(); } }