Introduction
CopyTree is a Backup Utility implementing Backup Rotation Scheme. It is an open source Windows Forms Application written in C#. The utility was designed to perform a backup of critical folders to multiple backup folders. The result of running the utility is that each backup folder is an exact copy of the source folder at a given time. Each time the utility is run, the oldest backup folder is updated with the current source folder. In other words, the utility rotates between the backup folders. The backup update process ensures that the backup directory structure is the same as the source directory. New files are copied from source to backup. Files that were deleted will be deleted from the backup. Files that were modified are copied over the old version. Files that were not modified are ignored. Except for the first time, the result is a very efficient backup process.
After the utility is installed, you select the critical folders on your hard disks for backup. We will call them the source folders. Next, you create several backup folders on an external hard drive or drives. My choice is three backup folders. Each time the utility is run, it will backup the source folders to the oldest of these backup folders. The result is that at any time, you have three generations of copies of your source folders. For example, if you run the utility once a day at the end of the day, on the next day you have a copy from yesterday, from the day before yesterday and from three days ago.
The copy process compares the source folder structure to the backup folder structure. If a file or sub-folder exists in the source and does not exist in the backup, the utility copies it from source to backup. If a file or sub-folder exists in the backup and does not exist in the source, the utility deletes it from the backup. If a file exists in both source and backup, the utility compares the LastWriteTimeUtc
of the source and the backup. If they are equal, the utility assumes that the file was not modified since last backup and no copy takes place. If the last write times are different, the utility copies the source file and overrides the old backup.
The file copy process preserves the file CreationTimeUtc
, LastWriteTimeUtc
and LastAccessTimeUtc
. Further, the file attribute flags: ReadOnly
, Hidden
, System
, Archive
and Normal
will be preserved. If a file is read only and there is a need to delete it or to override it, the read only flag will be removed. Source files that are in use by other applications on your computer cannot be copied. The exception will be trapped by try
-catch
pair and an error message will be displayed and logged. The backup process will continue.
Backup Schema
The backup schema consists of two lists. The backup list and the source list. Each list is made of records with two fields each.
- Backup Root Folders
- Last backup date and time
- Backup root folder name
- Backup Subfolder Name and Source Folders Paths
- Backup subfolder name
- Source folder path
Below, you will find an example of backup roots folder list. The list consists of three generations backup rotation on external hard disk drive G:.
- 2018/01/01 17:12:20 G:\Backup1
- 2018/01/02 17:35:43 G:\Backup2
- 2018/01/03 18:01:05 G:\Backup3
Let us assume that you want to backup your development projects that are stored in folder C:\MyDevelopment. And you want to backup your private documents folder, C:\MyDocuments. The Backup subfolder name and source folder paths will be:
- MyDevelopment C:\MyDevelopment
- MyDocuments C:\MyDocuments
If Backup1
is selected as the current backup, CopyTree
tree will copy C:\MyDevelopment to G:\Backup1\MyDevelopment folder. And C:\MyDocuments to G:\Backup1\MyDocuments.
CopyTree main screen
CopyTree edit schema screen
Demo Program
Create a folder CopyTree (or any other name) on your hard disk. Copy CopyTree.exe to this folder. Start the program. Click on the Edit Schema button.
The Edit Backup Schema window form will be displayed. Add one or more backup roots folders. My suggestion is three. Keep the suggested last backup time as the current time.
Add one or more source folder paths with their corresponding backup subfolders.
Click Save.
If the required backup root directory structure is not in place, CopyTree
will ask your permission to create it.
Press Go to perform a backup.
Backup progress will be displayed in the information text labels at the top of the screen.
The error log in the center of the screen will display errors. Normally, there will be no errors. The most common reason for a system exception is attempting to copy a file while the file is in use.
After backup is complete, you can press the View Log button or the View Errors button to see all activities.
Program Source Code
The Backup
class is the heart of the utility. The backup
class runs the actual backup process in a background thread using the BackgroundWorker
class.
The CopyTree
class shows how to create the Backup
class, how to initiate a backup, how to log the results, and how to be informed when the process is done.
Create backup
class and attach two event handlers.
Backup Backup = new Backup();
Backup.WriteToLogFile += WriteToLogFile;
Backup.BackupCompletedEvent += OnBackupCompleted;
Define write to log file event handler.
private void WriteToLogFile
(
LogControl Control,
string LogText
)
{
}
Define backup is completed event handler.
private void OnBackupCompleted
(
bool BackupDone
)
{
}
Initiate backup.
Schema.RootIndex = SelectedIndex;
Backup.BackupFolders(Schema);
The main method of the Backup
class is PerformFolderBackup
. It is a recursive method that traverses the source and backup folders tree.
private void PerformFolderBackup
(
DirectoryInfo SourceFolderInfo,
DirectoryInfo BackupFolderInfo
)
{
if(BackupWorker.CancellationPending) throw new CanceBackupException();
string BackupFolderFullName = BackupFolderInfo.FullName;
FileInfo[] SourceFiles = SourceFolderInfo.GetFiles();
FileInfo[] BackupFiles = BackupFolderInfo.GetFiles();
if(SourceFiles.Length != 0)
{
if(BackupFiles.Length != 0)
{
EqualizeFiles(SourceFiles, BackupFiles, BackupFolderFullName);
}
else
{
CopyFiles(SourceFiles, BackupFolderFullName);
}
}
else if(BackupFiles.Length != 0)
{
DeleteFiles(BackupFiles);
}
DirectoryInfo[] SourceFolders = SourceFolderInfo.GetDirectories();
DirectoryInfo[] BackupFolders = BackupFolderInfo.GetDirectories();
if(SourceFolders.Length != 0)
{
if(BackupFolders.Length != 0)
{
EqualizeFolders(SourceFolders, BackupFolders, BackupFolderFullName);
}
else
{
CreateFolders(SourceFolders, BackupFolderFullName);
}
}
else if(BackupFolders.Length != 0)
{
DeleteFolders(BackupFolders);
}
return;
}
Open Source Software Published by the Author
History
- 2017/08/01: Version 1.0 Original version
- 2017/08/09: Version 1.1 Change
DateTime.TryParse
out parameter to work with earlier C# compilers - 2017/08/01: Version 1.2 Fix for Go button enable status on first use of the program
- 2019/06/14: Version 1.3 Fix for unauthorized exception