实现备份轮换方案的备份工具 (C# 的开源 Windows Forms 应用程序)






4.96/5 (12投票s)
CopyTree 是一款实现备份轮换方案的备份工具。它是一个用 C# 编写的开源 Windows Forms 应用程序。该工具旨在将关键文件夹备份到多个备份文件夹。
引言
CopyTree 是一款实现备份轮换方案的备份工具。它是一个用 C# 编写的开源 Windows Forms 应用程序。该工具旨在将关键文件夹备份到多个备份文件夹。运行该工具的结果是,每个备份文件夹都是源文件夹在给定时间的精确副本。每次运行该工具时,最旧的备份文件夹都会用当前的源文件夹进行更新。换句话说,该工具在备份文件夹之间轮换。备份更新过程确保备份目录结构与源目录相同。新文件从源复制到备份。已删除的文件将从备份中删除。已修改的文件将覆盖旧版本。未修改的文件将被忽略。除了第一次,结果是一个非常高效的备份过程。
安装该工具后,您选择硬盘上需要备份的关键文件夹。我们称它们为源文件夹。接下来,您在外置硬盘或多个硬盘上创建几个备份文件夹。我选择三个备份文件夹。每次运行该工具时,它都会将源文件夹备份到这些备份文件夹中最旧的一个。结果是,在任何时候,您都有源文件夹的三代副本。例如,如果您每天结束时运行该工具一次,那么第二天您将拥有昨天、前天和三天前的副本。
复制过程将源文件夹结构与备份文件夹结构进行比较。如果文件或子文件夹存在于源中但不存在于备份中,则该工具将其从源复制到备份。如果文件或子文件夹存在于备份中但不存在于源中,则该工具将其从备份中删除。如果文件同时存在于源和备份中,则该工具比较源和备份的 LastWriteTimeUtc
。如果它们相等,则该工具假定自上次备份以来文件未被修改,并且不进行复制。如果最后写入时间不同,则该工具复制源文件并覆盖旧备份。
文件复制过程保留文件 CreationTimeUtc
、LastWriteTimeUtc
和 LastAccessTimeUtc
。此外,文件属性标志:ReadOnly
、Hidden
、System
、Archive
和 Normal
将被保留。如果文件是只读的,并且需要删除或覆盖它,则只读标志将被删除。计算机上其他应用程序正在使用的源文件无法复制。异常将由 try
-catch
对捕获,并将显示并记录错误消息。备份过程将继续。
备份方案
备份方案由两个列表组成。备份列表和源列表。每个列表都由包含两个字段的记录组成。
- 备份根文件夹
- 上次备份日期和时间
- 备份根文件夹名称
- 备份子文件夹名称和源文件夹路径
- 备份子文件夹名称
- 源文件夹路径
下面是备份根文件夹列表的示例。该列表包含外部硬盘驱动器 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
假设您想备份存储在文件夹 C:\MyDevelopment 中的开发项目。并且您想备份您的私人文档文件夹 C:\MyDocuments。备份子文件夹名称和源文件夹路径将是
- MyDevelopment C:\MyDevelopment
- MyDocuments C:\MyDocuments
如果选择 Backup1
作为当前备份,CopyTree
将把 C:\MyDevelopment 复制到 G:\Backup1\MyDevelopment 文件夹。并将 C:\MyDocuments 复制到 G:\Backup1\MyDocuments。
演示程序
在您的硬盘上创建一个文件夹 CopyTree(或任何其他名称)。将 CopyTree.exe 复制到此文件夹。启动程序。单击“编辑方案”按钮。
将显示“编辑备份方案”窗口表单。添加一个或多个备份根文件夹。我的建议是三个。将建议的上次备份时间保留为当前时间。
添加一个或多个源文件夹路径及其对应的备份子文件夹。
点击 **保存**。
如果所需的备份根目录结构不存在,CopyTree
将请求您的许可来创建它。
按 Go 执行备份。
备份进度将显示在屏幕顶部的“信息”文本标签中。
屏幕中央的错误日志将显示错误。通常,不会有错误。系统异常最常见的原因是文件正在使用时尝试复制文件。
备份完成后,您可以按 View Log 按钮或 View Errors 按钮查看所有活动。
程序源代码
Backup
类是该工具的核心。backup
类使用 BackgroundWorker
类在后台线程中运行实际的备份过程。
CopyTree
类展示了如何创建 Backup
类,如何启动备份,如何记录结果,以及如何在过程完成时收到通知。
创建 backup
类并附加两个事件处理程序。
// create backup class
Backup Backup = new Backup();
Backup.WriteToLogFile += WriteToLogFile;
Backup.BackupCompletedEvent += OnBackupCompleted;
定义写入日志文件事件处理程序。
/// <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
}
定义备份完成事件处理程序。
/// <summary>
/// Backup process is completed
/// </summary>
private void OnBackupCompleted
(
bool BackupDone // true=normal completion, false=user pressed cancel
)
{
// perform completed event tasks
}
启动备份。
// set the selected index of the backup folder list
Schema.RootIndex = SelectedIndex;
// initiate backup
Backup.BackupFolders(Schema);
Backup
类的主要方法是 PerformFolderBackup
。它是一个递归方法,遍历源和 backup 文件夹树。
/// <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
else
{
// 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
DeleteFiles(BackupFiles);
}
// 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
else
{
// 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
DeleteFolders(BackupFolders);
}
// done
return;
}
作者发布的开源软件
- PDF 文件写入 C# 类库 https://codeproject.org.cn/Articles/570682/PDF-File-Writer-Csharp-Class-Library
- “2013 年 4 月最佳综合文章”竞赛获奖者
- “2013 年 4 月最佳 C# 文章”竞赛获奖者
- PDF 文件写入器是一个 C# 类库,允许 .NET 应用程序创建 PDF 文件。
- 魔方初学者。带有 3D 图形和动画的开源 WPF C# 应用程序。 https://codeproject.org.cn/Articles/1199528/Rubik-s-Cube-for-Beginners-Open-Source-WPF-Csharp
- “2017 年 8 月最佳 C# 文章(一等奖)”竞赛获奖者
- 该程序将使用初学者算法解决魔方。它是一个使用 3D 图形和动画的 C# 编写的 WPF 开源应用程序。
- 带有 C# 解析类的 PDF 文件分析器 https://codeproject.org.cn/Articles/450254/PDF-File-Analyzer-With-Csharp-Parsing-Classes
- PDF 文件分析器旨在读取、解析和显示 PDF 文件的内部结构。
- 使用 C# 压缩/解压缩类处理标准 Zip 文件 https://codeproject.org.cn/Articles/359758/Processing-Standard-Zip-Files-with-Csharp-compress
- 该项目将为您提供使用
Deflate
压缩方法压缩和解压缩文件以及读取和写入标准 zip 文件所需的工具。
- 该项目将为您提供使用
- 支持隐式 SSL 安全套接字层与 OAuth2 开放授权或密码授权的 SMTP 客户端 https://codeproject.org.cn/Articles/1173678/SMTP-Client-Supporting-Implicit-SSL-Secure-Sockets
- 随附的开源 C# .NET 库是实现隐式 SSL 和 OAuth2 协议的 SMTP 客户端。
- 该库回答了以下问题:如何使用 Gmail 作为服务器发送电子邮件消息。或者,如何使用实现隐式 SSL 和端口 465 的电子邮件服务器发送电子邮件消息。
- 实现备份轮换方案的备份工具(C# 开源 Windows Forms 应用程序) https://codeproject.org.cn/Articles/1223887/Backup-Utility-implementing-Backup-Rotation-Scheme
CopyTree
是一款实现备份轮换方案的备份工具。它是一个用 C# 编写的开源 Windows Forms 应用程序。该工具旨在将关键文件夹备份到多个备份文件夹。
历史
- 2017/08/01:版本 1.0 原始版本
- 2017/08/09:版本 1.1 更改
DateTime.TryParse
输出参数以与早期 C# 编译器一起使用 - 2017/08/01:版本 1.2 修复了程序首次使用时 Go 按钮的启用状态问题
- 2019/06/14:版本 1.3 修复了未经授权的异常