为什么软件开发者应该编写自己的备份应用程序以及如何轻松做到






4.86/5 (14投票s)
在云存储时代,您应该如何组织备份并为其编写自己的应用程序
你为什么应该编写自己的备份程序?
我们中的许多人依赖于 **OneDrive** 或 **Google Drive** 等服务进行实时备份,以及 **GitHub** 或 **Azure DevOps** 来存储我们的源代码。如果你只做这些,你就有丢失所有备份数据的风险,因为
- 像 Google 这样的服务提供商可以锁定你的账户,你对此无能为力,你会丢失你所有的备份、照片和电子邮件。
- 病毒可以加密你的所有驱动器,由于它们会自动复制到云端,你再次丢失所有数据。
- 你可能不小心删除了一个文件,但过了一段时间才意识到。当然,该文件之后也会在云端被删除。
编写自己的备份程序的另一个原因是因为将所有数据复制到云端太贵了,例如你自己制作的视频文件或下载的音乐。
根据你的备份需求组织你的目录结构
你的文件根据你的使用方式和大小有不同的备份需求
- 重要文件,通常不大,例如 **MS Office** 文档:立即在线复制到云端,并**定期复制所有这些文件**到外部驱动器
- 软件开发文件:经常推送到 GitHub,并**定期复制所有这些文件**(不包含 *obj* 和 *bin* 目录)到外部驱动器。在这种情况下,你也可以不备份 *.git* 目录,但如果你很少推送,你也应该备份它。
- 内容变化不大的大文件,例如图片或电影:复制新文件并**更新更改的文件**到外部驱动器
- **归档**:大文件和许多文件集合,这些文件不再改变,即你多年来收集的文件:在新外部驱动器上复制一次所有内容。无需将其纳入备份运行。
根据备份需求将目录分组为几个主目录(云、仓库、归档)可能很有用。
保留重要文件及其原始内容的副本,即使它们后来被删除或更改。如果你在几个月后发现你错误地进行了操作,你仍然可以获取原始版本。
双驱动器备份
如果你的计算机中有两个驱动器,最快的备份方式是从一个驱动器到另一个驱动器。这种类型的备份在你第一个驱动器发生故障或你在该驱动器上出错时很有用。**但是**:仅此一项不足以作为备份。有一次我的电脑被盗了,如果没有外部备份,我就会丢失两个驱动器上的文件。因此,必须有一个外部驱动器,并将其保存在与 PC 不同的位置。当在线备份尚不可用时,我过去会每天快速备份到 PC 的第二个驱动器,有时也会备份到我的外部驱动器。现在有了云存储,我觉得不再需要每日备份了。
但是,你如何备份、备份到哪里以及备份的频率完全取决于你自己。因为你的需求可能与其他人的不同,例如软件开发人员不需要备份 *obj* 和 *bin* 目录,因为它们很大,并且 *VS* 可以重新创建它们。如果你只是下载一个备份程序,它将不支持这种功能,但如果你自己编写,你可以根据你的需求进行精确调整。
清理备份目录
当你定期将所有重要文件备份到外部硬盘驱动器时,它可能会很快被填满。这意味着你需要不时删除一些旧备份。最简单的方法就是删除最早的备份,但我推荐另一种程序
1) 我通常将外部硬盘驱动器填满到 90%。当发生这种情况时,我删除每第二个备份目录。
2..4) 每次我达到 90% 时,我再次删除每第二个备份目录。
这种方法的优点是,我仍然拥有第一个备份以及一些旧备份和许多最近的备份。这有两个优点
- 我不会丢失我获得外部驱动器时最早的文件。
- 错误通常发生在最近的文件中。因此,拥有过去几个月的不同副本很有帮助,但对于更早的时间则无需保留如此多的细节。
当然,实际上,我并没有那么自律,每个月都精确地进行备份。实际上,我只是在感觉我做了很多更改并且不想丢失它们时,不定期地备份到外部驱动器。有趣的是,删除每第二个备份目录的方法在这种情况下也有效。
编写自己的备份应用程序
最简单的方法是先从一个现有的应用程序开始,例如 `MyBackup`,然后添加你需要的功能。
MyBackup 应用程序概述
你可以在 GitHub 上找到它,链接如下:github.com/PeterHuberSg/MyBackup
在窗口的上部,用户可以在左侧输入每个备份应该完全复制的目录。程序将首先在 **备份路径** 创建一个新目录,目录名称为备份运行的日期。在该目录内,左侧列出的每个目录都会完全复制到该日期目录中。
右侧的目录将在第一次备份运行时完全复制到 **备份路径** 目录中,在后续运行中,只有新添加和已更改(名称相同但日期或大小不同)的文件会被复制。对于更新的文件,旧版本会丢失。
`执行` 启动备份,`清除` 删除日期目录中的每第二个目录
窗口的下部向用户显示哪些顶级目录已被备份,最后一行显示当前正在复制的文件。一次备份可能包含成千上万个文件,当然用户无法看到所有文件,因为小文件会很快被覆盖,或者出于性能原因甚至不会显示。但如果用户可以看到文件名,他就会知道当前正在复制哪个大文件,以及为什么备份进展不快。
当备份运行时,用户可以滚动,这将停止自动滚动,但一旦用户滚动回末尾,自动滚动将继续。
备份完成后,我喜欢查看输出中哪些目录很大,然后决定是否需要清理它们。
设计细节
以下是一些指针,可以帮助你快速上手,如果你想根据你的需求修改 `MyBackup`。
通常,我设置一个 WPF 应用程序包含三个库
- GUI
- 业务逻辑
- 业务逻辑测试
但是,由于 `MyBackup` 不需要太多代码,并且始终与 GUI 紧密交互,所以我将几乎所有内容都放入 `MainWindow.xaml.cs` 和几个 C# 文件中。
多线程
WPF 设计组织得相当巧妙。所有 UI 活动都在 WPF 线程上运行,这意味着在编写 UI 代码时没有多线程问题。但是,备份活动应该在另一个 `Thread` 上运行,否则 UI 会冻结。通常会创建一个 `Task`,它将在线程池线程上运行。然而,在这个应用程序中,我决定使用它自己的 `Thread`,因为应用程序的大部分运行时间都需要它。
这个线程应该向用户报告它正在做什么,基本上显示当前正在复制哪个文件。实际上,我注意到平均每秒有数百个文件!当然,并非所有这些文件都会被复制,大多数时候它们没有改变,不需要做任何事情。但是,每秒中断 WPF 数百次是一个坏主意。使用 `LogViewer` 可以解决这个问题。
LogViewer
我编写了一个特殊的 WPF 控件,请参阅我在 CodeProject 上的最新文章。
`LogViewer` 满足以下规格
- 多线程安全的消息日志记录
- 支持字体、粗体等,但使用 `LogViewer` 的代码不需要任何 WPF 依赖项。
- 区分临时消息和永久消息。临时消息会被任何后续消息覆盖,而永久消息在后台任务完成后仍会显示给用户。
- 收集所有收到的消息,并每 0.1 秒将它们一起传输到 WPF 线程。
实现这个目标是一项相当大的挑战。有关如何实现此目标的详细信息,请阅读我的文章。
存储设置数据
用户不希望每次运行 `MyBackup` 时都输入需要备份的目录。在.NET Framework 可能不太好的旧时代,可以使用 `Properties.Settings` 来轻松存储此类数据。在 **.NET 6** 中,WPF 模板不再提供此功能,我以此为契机自己实现了一个简单的数据存储。它是一个文本文件,存储用户输入的所有 `TextBox.Text` 数据,用 '`<-=#=>`' 分隔,这是一个用户可能永远不会输入的字符序列。
延伸阅读
如果你读到这里,你可能对 WPF 真正感兴趣,在这种情况下,我强烈推荐我的其他一些 WPF 文章。我觉得本文不太有趣,但我的有些文章非常有帮助,能让你对 WPF 有独特的见解。
- 深入 WPF 布局和渲染
- WPF 开发人员必读:WPF 控件测试平台
- WPF 颜色、颜色空间、颜色选择器和为普通人创建自己颜色的权威指南
- 使用绑定进行 WPF DataGrid 格式化的指南
- WPF DataGrid:解决排序、滚动到视图、刷新和焦点问题
- 避免 WPF DataGrid 的限制,用几行您自己的代码替换它
- WPF LinearGradientBrush 参数详解
- WPF 滚动条高级指南或如何显示数百万种颜色组合
- 提高 WPF DispatcherTimer 的精度
我在 GitHub 上的项目
我还编写了几个开源项目在 GitHub 上。
StorageLib | 对于单用户 WPF 应用程序,这是数据库的绝妙替代品。程序员只需定义他想使用的 C# 类,代码生成器就会编写所有代码,以便在本地磁盘上永久创建、更新和删除数据。这大大加快了开发者的工作速度,因为他不再需要使用任何 SQL、Entity Framework 等。查询使用 Linq 完成,并且运行速度非常快。代码的执行速度比任何数据库都快。支持事务、备份等等。在多个项目中已稳定运行 5 年以上。 |
TracerLib | 高效地实时收集多线程数据,这些数据可以存储在文件中,或者仅存储在 RAM 中并在一段时间后丢弃。这对于异常处理很有用,因为它允许告知用户异常发生之前发生了什么(!)。 |
WpfWindowsLib | 用于数据输入的 WPF 控件,检测是否缺少必需数据或数据是否已更改。 |
最后但同样重要的是一个很棒的游戏
我 6 年前写了 MasterGrab,从那时起,我几乎每天在开始编程之前都会玩它。击败 3 个试图争夺随机地图上所有 200 个国家的机器人大约需要 10 分钟。一旦一个玩家拥有所有国家,游戏就结束了。游戏很有趣,而且每天都感觉新鲜,因为地图每次看起来都完全不同。机器人带来了一些动态,它们互相竞争,也与人类玩家竞争。如果你愿意,你甚至可以编写自己的机器人,游戏是开源的。我大约花了两个星期写了我的机器人(整个游戏花了一年),但我对击败机器人感到惊讶。在与它们对战时,必须制定一个策略,让机器人互相攻击,而不是攻击你。我迟早会写一篇关于它的 CodeProject 文章,但你已经可以下载并玩它了。应用程序中有很好的帮助说明如何玩。
历史
- 2022 年 9 月 16 日:初始版本