Click here to Skip to main content
15,116,516 members
Articles / Programming Languages / C#
Posted 7 Jan 2018

Tagged as


33 bookmarked

Backup Utility implementing Backup Rotation Scheme (Open Source Windows Forms Application in C#)

Rate me:
Please Sign up or sign in to vote.
4.95/5 (10 votes)
14 Jun 2019CPOL6 min read
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 backup of critical folders to multiple backup folders.

Copy Tree Icon


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.

Copy Tree Main Screen

CopyTree main screen

Copy Tree Edit Schema

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.

// create backup class
Backup Backup = new Backup();
Backup.WriteToLogFile += WriteToLogFile;
Backup.BackupCompletedEvent += OnBackupCompleted;

Define write to log file event handler.

/// <summary>
/// Write to log file
/// </summary>
/// <param name="Control">Log or Error</param>
/// <param name="LogText">Message</param>
private void WriteToLogFile
    LogControl Control,  // LogControl is either Log or Error
    string LogText       // text
        // write to loe and error files

Define backup is completed event handler.

/// <summary>
/// Backup process is completed
/// </summary>
private void OnBackupCompleted
        bool BackupDone	// true=normal completion, false=user pressed cancel
    // perform completed event tasks

Initiate backup.

// set the selected index of the backup folder list
Schema.RootIndex = SelectedIndex;

// initiate backup

The main method of the Backup class is PerformFolderBackup. It is a recursive method that traverses the source and backup folders tree.

/// <summary>
/// recursive folder backup
/// </summary>
/// <param name="SourceFolderName">Source folder name</param>
/// <param name="BackupFolderName">Backup folder name</param>
private void PerformFolderBackup
    DirectoryInfo SourceFolderInfo,
    DirectoryInfo BackupFolderInfo
// cancel backup
if(BackupWorker.CancellationPending) throw new CanceBackupException();

// backup folder full name shortcut
string BackupFolderFullName = BackupFolderInfo.FullName;

// get source child files
FileInfo[] SourceFiles = SourceFolderInfo.GetFiles();

// get backup child files
FileInfo[] BackupFiles = BackupFolderInfo.GetFiles();

// source has files
if(SourceFiles.Length != 0)
    // backup has files
    if(BackupFiles.Length != 0)
        // backup has files
        EqualizeFiles(SourceFiles, BackupFiles, BackupFolderFullName);

    // backup has no files
        // copy all source files to backup folder
        CopyFiles(SourceFiles, BackupFolderFullName);

// source has no files but backup has files
else if(BackupFiles.Length != 0)
    // delete all files of backup folder
// get source child folders
DirectoryInfo[] SourceFolders = SourceFolderInfo.GetDirectories();

// get backup child folders
DirectoryInfo[] BackupFolders = BackupFolderInfo.GetDirectories();

// source has folders
if(SourceFolders.Length != 0)
    // backup has folders
    if(BackupFolders.Length != 0)
        // backup has folders
        EqualizeFolders(SourceFolders, BackupFolders, BackupFolderFullName);

    // backup has no folders
        // copy all source child folders to backup folder
        CreateFolders(SourceFolders, BackupFolderFullName);

// source has no folders but backup has folders
else if(BackupFolders.Length != 0)
    // delete all files of backup folder
// done

Open Source Software Published by the Author


  • 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


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Uzi Granot
Canada Canada
No Biography provided

Comments and Discussions

BugUnauthorizedAccessException Pin
harbor14-Jun-19 1:45
Memberharbor14-Jun-19 1:45 
GeneralRe: UnauthorizedAccessException Pin
Uzi Granot14-Jun-19 6:58
MemberUzi Granot14-Jun-19 6:58 
QuestionSyn Framework ? Pin
kiquenet.com9-Jun-18 0:08
professionalkiquenet.com9-Jun-18 0:08 
AnswerRe: Syn Framework ? Pin
Uzi Granot9-Jun-18 12:49
MemberUzi Granot9-Jun-18 12:49 
QuestionSources not in this server Pin
gil_tadiad10-Jan-18 5:41
Membergil_tadiad10-Jan-18 5:41 
AnswerRe: Sources not in this server Pin
Uzi Granot10-Jan-18 7:29
MemberUzi Granot10-Jan-18 7:29 
QuestionTrojan? Pin
Jeff Law8-Jan-18 16:00
MemberJeff Law8-Jan-18 16:00 
AnswerRe: Trojan? Pin
Uzi Granot9-Jan-18 2:36
MemberUzi Granot9-Jan-18 2:36 
AnswerRe: Trojan? Pin
Uzi Granot9-Jan-18 4:32
MemberUzi Granot9-Jan-18 4:32 
GeneralRe: Trojan? Pin
Jeff Law9-Jan-18 11:29
MemberJeff Law9-Jan-18 11:29 
GeneralRe: Trojan? Pin
TX64309-Jan-18 11:59
MemberTX64309-Jan-18 11:59 
GeneralRe: Trojan? Pin
TX64309-Jan-18 11:30
MemberTX64309-Jan-18 11:30 
GeneralRe: Trojan? Pin
TX64309-Jan-18 11:46
MemberTX64309-Jan-18 11:46 
GeneralRe: Trojan? Pin
Uzi Granot9-Jan-18 12:37
MemberUzi Granot9-Jan-18 12:37 
GeneralRe: Trojan? Pin
Jeff Law9-Jan-18 12:06
MemberJeff Law9-Jan-18 12:06 
GeneralRe: Trojan? Pin
Uzi Granot9-Jan-18 12:37
MemberUzi Granot9-Jan-18 12:37 
GeneralRe: Trojan? Pin
TX64309-Jan-18 22:40
MemberTX64309-Jan-18 22:40 
GeneralRe: Trojan? Pin
Uzi Granot10-Jan-18 3:37
MemberUzi Granot10-Jan-18 3:37 
GeneralRe: Trojan? Pin
TX643010-Jan-18 4:45
MemberTX643010-Jan-18 4:45 
QuestionCopyTree Compile error Pin
Paul G. Scannell8-Jan-18 11:18
MemberPaul G. Scannell8-Jan-18 11:18 
AnswerRe: CopyTree Compile error Pin
Uzi Granot8-Jan-18 12:21
MemberUzi Granot8-Jan-18 12:21 
AnswerRe: CopyTree Compile error Pin
Uzi Granot8-Jan-18 14:18
MemberUzi Granot8-Jan-18 14:18 
GeneralRe: CopyTree Compile error Pin
Paul G. Scannell9-Jan-18 4:12
MemberPaul G. Scannell9-Jan-18 4:12 
GeneralRe: CopyTree Compile error Pin
Uzi Granot9-Jan-18 4:17
MemberUzi Granot9-Jan-18 4:17 
GeneralRe: CopyTree Compile error Pin
Uzi Granot9-Jan-18 5:52
MemberUzi Granot9-Jan-18 5:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.