예제 #1
0
        /// <summary>
        /// 数据库备份逻辑,仅被一键备份调用
        /// </summary>
        private void sqlBackup()
        {
            string backupFolderPath = UserInfo.AppPath + "\\SQLBackup";

            if (!Directory.Exists(backupFolderPath))
            {
                Directory.CreateDirectory(backupFolderPath);
            }
            string backupFullPath    = backupFolderPath + "\\backupFull.bak";
            string backupDefPath     = backupFolderPath + "\\backupDef.bak";
            string backupDefLastPath = backupFolderPath + "\\backupDef_last.bak";

            ///完整备份可以在两个地方进行,一个时一键智能备份,一个时完整备份按钮,这两个无论怎样,
            ///都会覆盖完整备份的文件,所以,这里只要检测到完整备份的文件,就只做差异备份
            ///没有完整备份的文件,就做完整备份.
            ///每次完整备份之前,也要做完整备份的备份.
            ///检查完整备份文件是否存在,若存在,检查上次备份文件是否存在
            if (File.Exists(backupFullPath))
            {
                //有完整备份的文件,只做差异备份
                //如果有差异备份文件,则改名,再进行差异备份
                if (File.Exists(backupDefPath))
                {
                    File.Copy(backupDefPath, backupDefLastPath, true);
                }
                BackupAndRestored.BackUpDataBase(backupDefPath, UserInfo, listLog2, false);
            }
            else
            {
                //没有完整备份的文件,做完整备份
                BackupAndRestored.BackUpDataBase(backupFullPath, UserInfo, listLog2, true);
            }
        }
예제 #2
0
 /// <summary>
 /// 数据库完整还原按钮
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void fullRestoreDatabase_Click(object sender, EventArgs e)//完整还原按钮
 {
     using (OpenFileDialog fileDialog = new OpenFileDialog())
     {
         fileDialog.Filter = "(*.bak)|*.bak";
         if (fileDialog.ShowDialog() == DialogResult.OK)
         {
             //获取用户选择文件的后缀名
             //string extension = Path.GetExtension(fileDialog.FileName);
             //获取用户选择文件的文件名
             string fileName = Path.GetFileNameWithoutExtension(fileDialog.FileName);
             if (fileName.Contains("Full"))
             {
                 string[] strList = new string[] { fileDialog.FileName };
                 BackupAndRestored.FullRestoreDatabase(strList, this.UserInfo, listLog2, BacOrResType.Full);
             }
             else
             {
                 MessageBox.Show("请选择完整的备份文件(文件名中包含“Full”字样)");
                 listLog2.AddToButtom("数据库还原失败...文件格式错误");
                 listLog2.AddToButtom("请使用“完整还原”按钮重新选择备份文件");
             }
         }
     }
 }
예제 #3
0
        //数据库还原逻辑,仅被一键还原调用.
        public void restoredDataBase()
        {
            #region 数据库还原逻辑
            //todo:是否添加跳过数据库还原对话框.
            using (FolderBrowserDialog dialog = new FolderBrowserDialog())
            {
                string sqlBackupFileForderPath = ConfigHelper.GetAppConfig("sqlBackupFileForderPath");
                if (string.IsNullOrEmpty(sqlBackupFileForderPath))
                {
                    sqlBackupFileForderPath = this.UserInfo.AppPath + "\\SQLBackup";
                }
                DirectoryInfo TheFolder = new DirectoryInfo(sqlBackupFileForderPath);

                if (!TheFolder.Exists || TheFolder.GetFiles("*.bak").Length == 0)
                {
                    dialog.ShowNewFolderButton = true;
                    dialog.Description         = "数据库备份文件所在的文件夹";
                    //dialog.RootFolder = Environment.SpecialFolder.Recent;
                    if (dialog.ShowDialog(this) != DialogResult.OK)
                    {
                        listLog2.AddToButtom("未能选择文件夹,还原终止...");
                        return;
                    }
                    TheFolder = new DirectoryInfo(dialog.SelectedPath);
                }

                FileInfo[] fullFileInfo = TheFolder.GetFiles("backupFull.bak");
                FileInfo[] defFileInfo  = TheFolder.GetFiles("backupDef.bak");
                if (defFileInfo.Length > 0)
                {
                    //差异还原
                    if (fullFileInfo.Length == 0)
                    {
                        listLog2.AddToButtom("找不到备份文件,还原终止...");
                        return;
                    }
                    string[] backFiles = new string[] { TheFolder.FullName + "\\" + fullFileInfo[0].Name, TheFolder.FullName + "\\" + defFileInfo[0].Name };
                    BackupAndRestored.FullRestoreDatabase(backFiles, UserInfo, listLog2, BacOrResType.Def);
                }
                else
                {
                    //完整还原
                    //检查文件个数
                    if (fullFileInfo.Length == 0)
                    {
                        listLog2.AddToButtom("找不到备份文件,还原终止...");
                        return;
                    }
                    string[] backFiles = new string[] { TheFolder.FullName + "\\" + fullFileInfo[0].Name };
                    BackupAndRestored.FullRestoreDatabase(backFiles, UserInfo, listLog2, BacOrResType.Full);
                }
            }
            #endregion
        }
예제 #4
0
 /// <summary>
 /// 文件完整备份
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void skBtnFullFileBackup_Click(object sender, EventArgs e)
 {
     //完整备份就是不管目标快照,只将原文件夹和原备份文件夹做差异比较,拷贝多出的内容.
     #region 获取原文件夹路径
     string filesFolderPath;
     if (!getFilesFolderPath(out filesFolderPath))
     {
         listLog2.AddToButtom("没有找到要备份的文件路径,请先在设置里配置路径");
         listLog2.AddToButtom("备份结束...");
         return;
     }
     #endregion
     #region 将原文件夹生成临时快照
     List <string> filesGhost = createGhost(filesFolderPath);
     #endregion
     #region 比较临时快照和原备份快照
     if (Common.BackupGhost == null)
     {
         Common.BackupGhost = new FilesGhost()
         {
             FilesName = new List <string>()
         };
     }
     compareStrList(filesGhost, Common.BackupGhost.FilesName);
     if (filesGhost.Count < 1)
     {
         listLog2.AddToButtom("目标已包含所有文件,备份结束");
         return;
     }
     #endregion
     #region 获取原备份文件夹路径,保存变量名backupFilesFolderPath
     //原备份文件夹路径为
     string backupFilesFolderPath = UserInfo.AppPath + "\\BackupFiles";
     if (!Directory.Exists(backupFilesFolderPath))
     {
         Directory.CreateDirectory(backupFilesFolderPath);
     }
     #endregion
     #region 拷贝文件
     BackupAndRestored.RestoredFiles(filesGhost, filesFolderPath, backupFilesFolderPath, listLog2);
     #endregion
     #region 保存快照
     List <string> backupFileGhost = createGhost(backupFilesFolderPath);
     Common.SaveFileGhost(backupFileGhost, UserInfo.AppPath, true);
     #endregion
 }
예제 #5
0
        //数据库单独完整备份
        private void skBtnFullSqlBackup_Click(object sender, EventArgs e)
        {
            string backupFolderPath = UserInfo.AppPath + "\\SQLBackup";

            if (!Directory.Exists(backupFolderPath))
            {
                Directory.CreateDirectory(backupFolderPath);
            }
            string backupFullPath     = backupFolderPath + "\\backupFull.bak";
            string backupFullLastPath = backupFolderPath + "\\backupFull_last.bak";

            if (File.Exists(backupFullPath))
            {
                File.Copy(backupFullPath, backupFullLastPath, true);
            }
            BackupAndRestored.BackUpDataBase(backupFullPath, UserInfo, listLog2, true);
        }
예제 #6
0
 /// <summary>
 /// 数据库差异还原按钮
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 private void skinButton1_Click(object sender, EventArgs e)
 {
     using (OpenFileDialog fileDialog = new OpenFileDialog())
     {
         fileDialog.Filter      = "(*.bak)|*.bak";
         fileDialog.Multiselect = true;
         fileDialog.Title       = "同时选择完整备份和差异备份文件";
         if (fileDialog.ShowDialog() == DialogResult.OK)
         {
             if (fileDialog.FileNames.Length != 2)
             {
                 listLog2.AddToButtom("需同时选中完整备份和差异备份两个文件...");
                 listLog2.AddToButtom("还原终止...False");
                 return;
             }
             //int fullFile = 0;
             //int defFile = 0;
             string[] strList = new string[2];
             foreach (var item in fileDialog.FileNames)
             {
                 if (Path.GetFileNameWithoutExtension(item).Contains("Full"))
                 {
                     strList[0] = item;
                     //fullFile += 1;
                 }
                 else if (Path.GetFileNameWithoutExtension(item).Contains("Def"))
                 {
                     strList[1] = item;
                     //defFile += 1;
                 }
             }
             if (string.IsNullOrEmpty(strList[0]) || string.IsNullOrEmpty(strList[1]))
             {
                 listLog2.AddToButtom("所选文件名称不正确(需包含\"full\"或\"def\")");
                 listLog2.AddToButtom("还原终止...False");
                 return;
             }
             BackupAndRestored.FullRestoreDatabase(strList, this.UserInfo, listLog2, BacOrResType.Def);
         }
     }
 }
예제 #7
0
        /// <summary>
        /// 文件备份逻辑
        /// </summary>
        private void filesBackup()
        {
            ///弹出文件备份选择要备份文件夹的对话框
            ///todo:做分散备份的工作,防止一个硬盘放不下
            ///先看有没有目标快照,有的话,比较目标快照和原文件夹,做差异备份,没有,做完整备份.
            ///完整备份,先看有没有完整备份快照,有的话,比较备份快照和原文件夹,进行差异备份,没有,完整备份全部文件
            ///备份完后,将原文件夹生成快照.
            ///
            //按照上面逻辑,所有的备份都要用到原文件夹和原备份文件夹,所以,先将原文件夹生成临时快照,生成的临时快照集合为filesGhost
            #region 获取原文件夹路径
            //todo:在程序界面加入配置选项按钮,可以设置各种路径
            //首先在配置文件中找原文件夹的路径配置,如果没有找到,则提示配置,保存在filesFolderPath变量中.
            string filesFolderPath;
            if (!getFilesFolderPath(out filesFolderPath))
            {
                listLog2.AddToButtom("没有找到要备份的文件路径,请先在设置里配置路径");
                listLog2.AddToButtom("备份结束...");
                return;
                //todo:添加设置按钮.
            }
            #endregion
            #region 生成原文件夹临时快照集合为filesGhost
            //DirectoryInfo TheFolder = new DirectoryInfo(filesFolderPath);
            //DirectoryInfo[] filesInfo = TheFolder.GetDirectories();
            //List<string> filesGhost = new List<string>();//原文件夹临时快照集合
            //foreach (var item in filesInfo)
            //{
            //    filesGhost.Add(item.Name);
            //}
            List <string> filesGhost = createGhost(filesFolderPath);
            #endregion
            #region 获取原备份文件夹路径,保存变量名backupFilesFolderPath
            //原备份文件夹路径为
            string backupFilesFolderPath = UserInfo.AppPath + "\\BackupFiles";
            if (!Directory.Exists(backupFilesFolderPath))
            {
                Directory.CreateDirectory(backupFilesFolderPath);
            }
            #endregion
            #region 判断是完整备份还是差异备份的逻辑
            if (Common.RestorGhost == null)
            {
                //做完整备份
                if (Common.BackupGhost == null)
                {
                    //备份所有文件
                    BackupAndRestored.RestoredFiles(filesGhost, filesFolderPath, backupFilesFolderPath, listLog2);
                }
                else
                {
                    //备份原快照和原文件夹的差异
                    List <string> backupFileGhostClong = new List <string>(Common.BackupGhost.FilesName);
                    List <string> filesGhostClong      = new List <string>(filesGhost);
                    compareStrList(backupFileGhostClong, filesGhostClong);
                    if (filesGhostClong.Count < 1)
                    {
                        listLog2.AddToButtom("备份文件夹已包含所有内容...");
                        return;
                    }
                    else
                    {
                        BackupAndRestored.RestoredFiles(filesGhostClong, filesFolderPath, backupFilesFolderPath, listLog2);
                    }
                }
            }
            else
            {
                //做目标快照和原文件夹的差异快照
                //差异快照再和原备份文件夹快照比较,生成最终要拷贝的文件快照
                List <string> restoredFileGhostClong = new List <string>(Common.RestorGhost.FilesName);
                List <string> filesGhostClong        = new List <string>(filesGhost);
                List <string> backupFileGhostClong   = new List <string>(Common.BackupGhost.FilesName);
                compareStrList(restoredFileGhostClong, filesGhostClong);
                if (filesGhostClong.Count < 1)
                {
                    listLog2.AddToButtom("本期没有增加任何文件");
                    return;
                }
                compareStrList(filesGhostClong, backupFileGhostClong);
                if (filesGhostClong.Count < 1)
                {
                    listLog2.AddToButtom("目标文件夹已包含所有内容...");
                    return;
                }
                BackupAndRestored.RestoredFiles(filesGhostClong, filesFolderPath, backupFilesFolderPath, listLog2);
            }
            #endregion

            //生成快照
            #region 保存快照
            List <string> backupFileGhost = createGhost(backupFilesFolderPath);
            Common.SaveFileGhost(backupFileGhost, UserInfo.AppPath, true);
            #endregion
        }
예제 #8
0
        /// <summary>
        /// 文件还原按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void skBtnFullFileRestor_Click(object sender, EventArgs e)
        {
            //todo:(已完成)等写完一键还原方法后,再补充
            ///完整还原的逻辑
            ///就是要把原文件夹所有的文件都复制到目标去,不做任何比较
            ///唯一需要校验的时原快照和原文件夹是否相符
            ///但无论是否相符,都会复制所有文件,最后要提示缺少哪些文件.

            //获取原快照
            #region 检查是否加载快照
            //判断Common里面,是否有备份快照,如果没有,弹出对话框提示选择,没有选择,则直接return
            if (Common.BackupGhost == null)
            {
                using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                {
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        int fileGhostResult = Common.getFileGhost(listLog2, dialog.SelectedPath);
                        while (fileGhostResult == 1 || fileGhostResult == 3)
                        {
                            listLog2.AddToButtom("请选择包含备份快照文件的文件夹");
                            if (dialog.ShowDialog() != DialogResult.OK)
                            {
                                return;
                            }
                            fileGhostResult = Common.getFileGhost(listLog2, dialog.SelectedPath);
                        }
                    }
                    else
                    {
                        listLog2.AddToButtom("没有找到备份快照文件,还原无法继续...False");
                        return;
                    }
                }
            }
            #endregion

            //获取原文件夹路径,生成快照
            #region 获取原备份文件夹路径
            //一般情况下,由程序一键备份生成的备份文件,路径为"程序所在目录\BackupFiles",存放在backupFilesFolderPath变量中

            //todo:添加目录不存在的选择文件夹的逻辑
            string backupFilesFolderPath = UserInfo.AppPath + "\\BackupFiles";
            if (!Directory.Exists(backupFilesFolderPath))
            {
                listLog2.AddToButtom("资料备份文件不存在...还原结束");
                return;
            }
            #endregion
            #region 获取原备份文件夹实例,并生成临时快照backupFilesGhost,备用
            DirectoryInfo   TheFolder       = new DirectoryInfo(backupFilesFolderPath);//todo:备份文件如果一个硬盘放不下,则添加选择路径逻辑
            DirectoryInfo[] backupFilesInfo = TheFolder.GetDirectories();
            //List<string> backupFileGhostClong = new List<string>(Common.BackupGhost.FilesName);//将原快照进行复制,以保留原快照内容
            List <string> backupFilesGhost = new List <string>(); // 原备份文件夹快照
            foreach (var item in backupFilesInfo)                 //生成原备份文件夹快照
            {
                backupFilesGhost.Add(item.Name);
            }
            #endregion

            //比较,生成差异快照
            List <string> backupFileGhostClong = new List <string>(Common.BackupGhost.FilesName);//将原快照进行复制,以保留原快照内容
            compareStrList(backupFileGhostClong, backupFilesGhost);

            //获得目标文件夹路径
            #region 获取目标文件夹路径,保存在restoredFilesFolderPath变量中.
            //查找配置文件里是否有目标文件夹的配置,如果有,加载,如果没有,则弹出对话框选择目标文件夹,并且记录到配置文件.配置文件保存目标文件夹目录的Name为restoredFilesFolderPath
            //将获取到的路径保存到配置文件和内存restoredFilesFolderPath变量中.
            //-----------------------------------获取目标文件夹路径(开始)---------------------------------------
            string restoredFilesFolderPath = ConfigHelper.GetAppConfig("restoredFilesFolderPath");
            if (string.IsNullOrEmpty(restoredFilesFolderPath))
            {
                if (MessageBox.Show("确定将开始选择还原资料文件的目标路径\r\n取消将终止还原", "没有找到还原路径", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                {
                    listLog2.AddToButtom("还原终止,请重新运行还原程序...");
                    return;
                }
                //listLog2.AddToButtom("没有找到目标文件夹,请先选择要还原的目标路径");
                using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                {
                    dialog.ShowNewFolderButton = true;
                    if (dialog.ShowDialog() != DialogResult.OK)
                    {
                        listLog2.AddToButtom("还原终止,请重新运行还原程序...");
                        return;
                    }
                    //当用户选择了一个文件夹后,进行进一步询问,防止选错.
                    if (MessageBox.Show("当前选择路径\r\n" + dialog.SelectedPath + "\r\n取消将终止还原\r\n可在程序设置里重新配置此路径", "确定要在此位置进行还原吗?", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                    {
                        listLog2.AddToButtom("还原终止,请重新运行还原程序...");
                        return;
                    }
                    //运行到这里,说明选择了目标路径,将路径写入配置文件
                    restoredFilesFolderPath = dialog.SelectedPath;
                    ConfigHelper.UpdateAppConfig("restoredFilesFolderPath", restoredFilesFolderPath);
                }
            }
            //todo:(重要,必须添加,否则还原无限终止)添加第一次运行还原时,如果读取到配置文件已经设置了路径,弹出对话框,用户确认后继续,不确认重新弹出选择路径对话框,有三个按钮:确认/重选/终止.
            //-----------------------------------获取目标文件夹路径(结束)---------------------------------------
            #endregion
            //拷贝文件
            BackupAndRestored.RestoredFiles(backupFilesGhost, backupFilesFolderPath, restoredFilesFolderPath, listLog2);
            //提示缺少
            //如果文件有缺少(即原快照有剩余)提示缺少
            if (backupFileGhostClong.Count > 0)
            {
                foreach (var item in backupFileGhostClong)
                {
                    listLog2.AddToButtom("缺少文件夹..." + item);
                }
                listLog2.AddToButtom("请查找以上文件,并拷贝到程序目录\\BackupFiles文件夹中");//todo:考虑做成弹出窗体利用listview形式进行展示.
            }
            //保存快照到文件
            #region 保存目标快照
            TheFolder = new DirectoryInfo(restoredFilesFolderPath);//使用原快照和原文件夹对比时创建的变量.
            //todo:添加比较原快照和目标目录Size大小功能
            DirectoryInfo[] restoredFilesInfo = TheFolder.GetDirectories();
            List <string>   restoredFileGhost = new List <string>();
            foreach (var item in restoredFilesInfo)
            {
                restoredFileGhost.Add(item.Name);
            }
            Common.SaveFileGhost(restoredFileGhost, UserInfo.AppPath, false);
            #endregion
        }
예제 #9
0
        //资料文件还原逻辑,仅被一键还原调用和增量还原调用.
        public void restoredFill()
        {
            #region 文件还原逻辑
            ///先判断快照文件是否存在,还原时,所有快照都要使用.
            ///如果快照都存在,比较目标文件夹和目标快照是否相符,不符则生成差异快照(RestoredDef).(按逻辑,在没有外界因素干扰下,目标文件夹不会比目标快照多,多出来的也是无用文件,不用管)
            ///(本行逻辑有误,跳过)如果相符,比较原快照和原文件夹是否相符(一般都是程序生成,一般是相符的),不符则生成差异快照(BackupDef)
            ///如果相符,比较原快照和目标快照,生成差异快照(fillDefNow)
            ///比较fillDefNow和原文件夹,看原文件夹里是否包含fillDefNow所有文件
            ///如果不包含,列出列表\
            ///如果包含,执行还原

            #region 检查是否加载快照
            //判断Common里面,是否有备份快照,如果没有,弹出对话框提示选择,没有选择,则直接return
            if (Common.BackupGhost == null)
            {
                using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                {
                    listLog2.AddToButtom("选择包含备份快照文件的文件夹");
                    if (dialog.ShowDialog() == DialogResult.OK)
                    {
                        int fileGhostResult = Common.getFileGhost(listLog2, dialog.SelectedPath);
                        while (fileGhostResult == 1 || fileGhostResult == 3)
                        {
                            listLog2.AddToButtom("请选择包含备份快照文件的文件夹");
                            if (dialog.ShowDialog() != DialogResult.OK)
                            {
                                listLog2.AddToButtom("没有找到备份快照文件,还原无法继续...False");
                                return;
                            }
                            fileGhostResult = Common.getFileGhost(listLog2, dialog.SelectedPath);
                        }
                    }
                    else
                    {
                        listLog2.AddToButtom("没有找到备份快照文件,还原无法继续...False");
                        return;
                    }
                }
            }
            #endregion
            //运行到这里,说明快照加载至少有备份快照,开始比较快照
            //Common.BackupGhost是主机备份后生成的原快照.Common.RestorGhost是目标还原后生成的目标快照
            #region 首先对比原快照与目标快照的差异,生成差异快照.然后对比差异快照和原备份文件夹,判断原备份文件夹内容是否齐全.

            #region 获取原备份文件夹路径
            //一般情况下,由程序一键备份生成的备份文件,路径为"程序所在目录\BackupFiles",存放在backupFilesFolderPath变量中
            //这里应至少包含最后一次增量的所有文件.先获取,等比较完备份快照和还原快照后再和其比较
            //todo:添加目录不存在的选择文件夹的逻辑
            string backupFilesFolderPath = UserInfo.AppPath + "\\BackupFiles";
            if (!Directory.Exists(backupFilesFolderPath))
            {
                listLog2.AddToButtom("资料备份文件不存在...还原结束");
                return;
            }
            #endregion

            #region 获取原备份文件夹实例,并生成临时快照backupFilesGhost,备用
            DirectoryInfo   TheFolder       = new DirectoryInfo(backupFilesFolderPath);//todo:备份文件如果一个硬盘放不下,则添加选择路径逻辑
            DirectoryInfo[] backupFilesInfo = TheFolder.GetDirectories();
            //List<string> backupFileGhostClong = new List<string>(Common.BackupGhost.FilesName);//将原快照进行复制,以保留原快照内容
            List <string> backupFilesGhost = new List <string>(); // 原备份文件夹快照
            foreach (var item in backupFilesInfo)                 //生成原备份文件夹快照
            {
                backupFilesGhost.Add(item.Name);
            }
            #region 逻辑错误,不进行比较
            //compareStrList(backupFileGhostClong, backupFilesGhost);
            //if (backupFileGhostClong.Count > 0)
            //{
            //    listLog2.AddToButtom("备份文件数量不符...丢失");
            //    foreach (var item in backupFileGhostClong)
            //    {
            //        listLog2.AddToButtom(item);
            //    }
            //    listLog2.AddToButtom("请查找以上文件,并拷贝到程序目录\\BackupFiles文件夹中");
            //    return;
            //}
            #endregion
            #endregion

            #region 获取目标文件夹路径,保存在restoredFilesFolderPath变量中.
            //查找配置文件里是否有目标文件夹的配置,如果有,加载,如果没有,则弹出对话框选择目标文件夹,并且记录到配置文件.配置文件保存目标文件夹目录的Name为restoredFilesFolderPath
            //将获取到的路径保存到配置文件和内存restoredFilesFolderPath变量中.
            //-----------------------------------获取目标文件夹路径(开始)---------------------------------------
            string restoredFilesFolderPath = ConfigHelper.GetAppConfig("restoredFilesFolderPath");
            if (string.IsNullOrEmpty(restoredFilesFolderPath))
            {
                if (MessageBox.Show("确定将开始选择还原资料文件的目标路径\r\n取消将终止还原", "没有找到还原路径", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                {
                    listLog2.AddToButtom("还原终止,请重新运行还原程序...");
                    return;
                }
                //listLog2.AddToButtom("没有找到目标文件夹,请先选择要还原的目标路径");
                using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                {
                    dialog.ShowNewFolderButton = true;
                    if (dialog.ShowDialog() != DialogResult.OK)
                    {
                        listLog2.AddToButtom("还原终止,请重新运行还原程序...");
                        return;
                    }
                    //当用户选择了一个文件夹后,进行进一步询问,防止选错.
                    if (MessageBox.Show("当前选择路径\r\n" + dialog.SelectedPath + "\r\n取消将终止还原\r\n可在程序设置里重新配置此路径", "确定要在此位置进行还原吗?", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) != DialogResult.OK)
                    {
                        listLog2.AddToButtom("还原终止,请重新运行还原程序...");
                        return;
                    }
                    //运行到这里,说明选择了目标路径,将路径写入配置文件
                    restoredFilesFolderPath = dialog.SelectedPath;
                    ConfigHelper.UpdateAppConfig("restoredFilesFolderPath", restoredFilesFolderPath);
                }
            }
            //todo:(重要,必须添加,否则还原无限终止)添加第一次运行还原时,如果读取到配置文件已经设置了路径,弹出对话框,用户确认后继续,不确认重新弹出选择路径对话框,有三个按钮:确认/重选/终止.
            //-----------------------------------获取目标文件夹路径(结束)---------------------------------------
            #endregion

            #region 生成目标文件夹临时快照restoredFileGhost,与原快照进行比较,比较后,原快照保留的内容即本次还原的增量
            //---------------对比原快照和目标文件夹(开始)-------------------------
            //获取目标文件夹内子文件夹的集合
            if (!Directory.Exists(restoredFilesFolderPath))
            {
                listLog2.AddToButtom("配置文件中目标文件夹路径有误,请在程序设置中重新配置...");
                return;
            }
            TheFolder = new DirectoryInfo(restoredFilesFolderPath);//使用原快照和原文件夹对比时创建的变量.
            //todo:添加比较原快照和目标目录Size大小功能
            DirectoryInfo[] restoredFilesInfo    = TheFolder.GetDirectories();
            List <string>   restoredFileGhost    = new List <string>();
            List <string>   backupFileGhostClong = new List <string>(Common.BackupGhost.FilesName);//将原快照进行复制,以保留原快照内容
            foreach (var item in restoredFilesInfo)
            {
                restoredFileGhost.Add(item.Name);
            }
            compareStrList(backupFileGhostClong, restoredFileGhost);
            if (backupFileGhostClong.Count < 1)
            {
                listLog2.AddToButtom("目标文件夹已包含所有内容...");
                return;
            }
            //正常情况下,比较完成后,backupFileGhostClong里面会有剩余,内容为备份快照与目标文件夹多出来的部分.即增量
            //todo:是否加入对目标快照也有剩余,并进行删除的逻辑.
            //---------------对比原快照和目标文件夹(结束)-------------------------
            #endregion

            #region 将增量与原备份文件夹进行比较,如果文件夹缺少内容,提示补全,否则开始还原.
            //----------------检查原备份文件夹下是否包含所有增量文件(开始)-------------
            List <string> backupFileGhostClongClong = new List <string>(backupFileGhostClong); //将差异快照再次备份一份,作用只是进行比较,不参与还原.
            compareStrList(backupFileGhostClongClong, backupFilesGhost);                       //进行比较
            if (backupFileGhostClongClong.Count > 1)
            {
                listLog2.AddToButtom("备份文件数量不符...丢失");
                foreach (var item in backupFileGhostClongClong)
                {
                    listLog2.AddToButtom("缺少文件夹..." + item);
                    backupFileGhostClong.Remove(item);
                }
                listLog2.AddToButtom("请查找以上文件,并拷贝到程序目录\\BackupFiles文件夹中");//todo:考虑做成弹出窗体利用listview形式进行展示.
                return;
            }
            //----------------检查原备份文件夹下是否包含所有增量文件(结束)-------------
            #endregion
            ///执行到这里,说明
            ///1.备份快照与目标文件夹已经比较.
            ///2.备份快照与目标文件夹的增量已经与备份文件夹进行比较.
            ///3.备份文件夹文件齐全.
            ///开始进行还原.
            //----------------------开始执行还原(开始)-------------------
            //(废弃)调用一个还原的函数,通过参数指定是全部还原还是增量还原.
            //上面一行注释逻辑不清晰,还原文件不用指定全部还原和增量还原,传给函数一个快照对象,按照快照进行复制即可.
            //backupFileGhostClong里面所包含的内容,是全部的增量,且所有的增量都有一个文件夹对应
            if (backupFileGhostClong.Count < 1)
            {
                listLog2.AddToButtom("没有进行任何复制,还原退出...");
                return;
            }
            BackupAndRestored.RestoredFiles(backupFileGhostClong, backupFilesFolderPath, restoredFilesFolderPath, listLog2);
            //----------------------开始执行还原(结束)-------------------
            #endregion
            #endregion

            #region 保存目标快照
            TheFolder = new DirectoryInfo(restoredFilesFolderPath);//使用原快照和原文件夹对比时创建的变量.
            //todo:添加比较原快照和目标目录Size大小功能
            restoredFilesInfo = TheFolder.GetDirectories();
            foreach (var item in restoredFilesInfo)
            {
                restoredFileGhost.Add(item.Name);
            }
            Common.SaveFileGhost(restoredFileGhost, UserInfo.AppPath, false);
            #endregion
        }