2018年7月7日
开发工具VS2013 .net 框架 2.0
SQL server的备份文件只可以备份在本机,只有一份,这个软件可以定时把备份文件拷贝到别的机器,作为另外的备份,还可以在成功备份后自动删除过期的文件,没有成功备份,不删除过期文件,以免误删,除非手动删除。
拷贝文件过程中没有进度条提示。
写了4个类,没写字段和属性,只写方法,很简单。
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Ini.cs //读写配置文件,使用设置可以保存下来,下次打开软件,不用重新设置
1 using System; 2 using System.Collections.Generic; 3 using System.Text; 4 using System.Runtime.InteropServices; 5 6 namespace AutoCopy 7 { 8 class Ini 9 { 10 [DllImport("kernel32")] 11 private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); 12 [DllImport ("kernel32")] 13 private static extern int GetPrivateProfileString(string section, string key, string def,StringBuilder retVal, int size,string filePath); 14 15 /// <summary> 16 /// 读取ini 17 /// </summary> 18 /// <param name="group">数据分组</param> 19 /// <param name="key">关键字</param> 20 /// <param name="default_value"></param> 21 /// <param name="filepath">ini文件地址</param> 22 /// <returns>关键字对应的值,没有时用默认值</returns> 23 public static string readini(string group, string key, string default_value, string filepath) 24 { 25 StringBuilder temp = new StringBuilder(); 26 GetPrivateProfileString(group,key,default_value,temp, 255, filepath); 27 return temp.ToString(); 28 } 29 /// <summary> 30 /// 存储ini 31 /// </summary> 32 /// <param name="group">数据分组</param> 33 /// <param name="key">关键字</param> 34 /// <param name="value">关键字对应的值</param> 35 /// <param name="filepath">ini文件地址</param> 36 public static void writeini(string group, string key, string value, string filepath) 37 { 38 WritePrivateProfileString(group, key, value, filepath); 39 } 40 41 } 42 }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
FileOprater.cs //文件操作类,
1 using System; 2 using System.Collections; 3 using System.Collections.Generic; 4 using System.IO; 5 using System.Text; 6 using System.Windows.Forms; 7 8 namespace AutoCopy 9 { 10 class FileOprater 11 { 12 public FileOprater(){} 13 14 /// <summary> 15 /// 读取路径上的文件列表 16 /// </summary> 17 /// <param name="Path">文件路径</param> 18 /// <param name="compare"> == 或者 >= </param> 19 /// <param name="days">用numberUpDown的值</param> 20 /// <returns></returns> 21 public ArrayList getFileList(string Path, string compare, int days) 22 { 23 try 24 { 25 string[] dir = Directory.GetFiles(Path); 26 ArrayList _fileList = new ArrayList(); 27 for (int dirIndex = 0; dirIndex < dir.Length; dirIndex++) 28 { 29 DateTime fileLastWriteTime = File.GetLastWriteTime(dir[dirIndex].ToString()); 30 TimeSpan timespan = DateTime.Today.Date - fileLastWriteTime.Date; 31 if (compare == "==") 32 { 33 if (timespan.Days == 0) 34 { 35 _fileList.Add(dir[dirIndex].ToString()); 36 } 37 } 38 else 39 { 40 //TimeSpan timespan = DateTime.Today.Date - fileLastWriteTime.Date; 41 if (timespan.Days >= days) 42 { 43 _fileList.Add(dir[dirIndex].ToString()); 44 } 45 } 46 47 } 48 return _fileList; 49 } 50 catch(Exception e) 51 { 52 MessageBox.Show(e.ToString(),"错误",MessageBoxButtons.OK,MessageBoxIcon.Error); 53 return null; 54 55 } 56 57 } 58 59 /// <summary> 60 /// 拷贝文件,用FileStream buffer来写入,大文件也没问题 61 /// </summary> 62 /// <param name="SourcePath">源文件路径</param> 63 /// <param name="DestinyPath">目标文件路径</param> 64 public void CopyFiles(string SourcePath, string DestinyPath) 65 { //1创建一个负责读取的流 66 using (FileStream fsRead = new FileStream(SourcePath, FileMode.Open, FileAccess.Read)) 67 {//创建一个负责写入的流 68 using (FileStream fsWrite = new FileStream(DestinyPath, FileMode.OpenOrCreate, FileAccess.Write)) 69 { 70 byte[] buffer = new byte[1024 * 1024 * 5]; 71 while (true) 72 { 73 int r = fsRead.Read(buffer, 0, buffer.Length); 74 //如果返回一个0,就意味什么都没有读取到,读取完了 75 if (r == 0) 76 { 77 break; 78 } 79 fsWrite.Write(buffer, 0, r); 80 } 81 } 82 83 } 84 85 } 86 87 public void DeleteFiles(string Path) 88 { 89 File.Delete(Path); 90 91 } 92 93 } 94 }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
MyListBox.cs
//把文件显示在列表框的类
using System; using System.Collections.Generic; using System.Text; using System.IO; using System.Windows.Forms; using System.Collections; namespace AutoCopy { class MyListBox { public MyListBox() { } internal Boolean showFilesList(ArrayList fileList,ListBox listbox ) { //定义数组,用于保存文件路径 if (fileList != null) { for (int index = 0; index < fileList.Count; index++) { listbox.Items.Add(fileList[index].ToString()); } return true; } else return false; } } }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LogWriter.cs
//最后的这个是写入日志文件的类。
using System; using System.Collections.Generic; using System.Text; using System.IO; namespace AutoCopy { class LogWriter { public LogWriter() { } internal void writeLog(string str) { string AppPath = System.Windows.Forms.Application.StartupPath + "\\Log.txt"; if (!File.Exists(AppPath)) { File.CreateText(AppPath); } using (FileStream fs = new FileStream(AppPath, FileMode.Append, FileAccess.Write)) { Byte[] info = new UTF8Encoding(true).GetBytes(DateTime.Now.ToString() + " "+str+"\r\n"); // Add some information to the file. fs.Write(info, 0, info.Length); } } } }
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Form1.cs //界面里的操作代码写的有点多,显得有点零乱。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Collections; namespace AutoCopy { public partial class Form1 : Form { public Form1() { InitializeComponent(); } //源文件目录浏览按钮 private void buttonSource_Click(object sender, EventArgs e) { folderBrowserDialog1.ShowDialog(); textBoxSource.Text = folderBrowserDialog1.SelectedPath.ToString(); } //目标文件目录浏览按钮 private void buttonDestiny_Click(object sender, EventArgs e) { folderBrowserDialog1.ShowDialog(); textBoxDestiny.Text = folderBrowserDialog1.SelectedPath.ToString(); } //新建FileOprater对象 FileOprater fo=new FileOprater(); //新建MyListBox对象 MyListBox mylistbox=new MyListBox(); //新建LogWriter对象 LogWriter lw = new LogWriter(); //新建Ini对象 //Ini ini = new Ini(); //托盘区图标功能 private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e) { if (WindowState == FormWindowState.Minimized) { //还原窗体显示 WindowState = FormWindowState.Normal; //激活窗体并给予它焦点 this.Activate(); //任务栏区显示图标 this.ShowInTaskbar = true; //托盘区图标隐藏 notifyIcon1.Visible = false; } } //隐藏程序窗口到托盘区 private void Form1_SizeChanged(object sender, EventArgs e) { if (WindowState == FormWindowState.Minimized) { //隐藏任务栏区图标 this.ShowInTaskbar = false; //图标显示在托盘区 notifyIcon1.Visible = true; } } //关闭程序确认对话框 private void Form1_FormClosing(object sender, FormClosingEventArgs e) { if (MessageBox.Show("是否确定退出程序?","退出",MessageBoxButtons.OKCancel,MessageBoxIcon.Question) == DialogResult.OK) { //关闭所有的进程 this.Dispose(); this.Close(); } else { e.Cancel = true; } } private void buttonOK_Click(object sender, EventArgs e) { TodayFileslistBox.Items.Clear(); //清空列表框 mylistbox.showFilesList(fo.getFileList(textBoxSource.Text.Trim(),"==",0),TodayFileslistBox);//显示文件列表在列表框 if (TodayFileslistBox.Items != null) //如果列表不为空(有文件) { for (int i = 0; i < TodayFileslistBox.Items.Count; i++) //循环 { string strName = TodayFileslistBox.Items[i].ToString().Substring(TodayFileslistBox.Items[i].ToString().LastIndexOf("\\")); try { StatusLabel2.Text = strName + "正在复制"; fo.CopyFiles(TodayFileslistBox.Items[i].ToString(), textBoxDestiny.Text + strName); StatusLabel2.Text = strName + " 复制完成"; lw.writeLog(TodayFileslistBox.Items[i].ToString() + " 复制成功");//写入日志文件 //以上代码跟Timer1的执行代码有重复,下面也有说明 } catch (Exception ex) { StatusLabel2.Text = "备份过程出错,请查看日志文件Log.txt"; lw.writeLog(ex.ToString()); } } } } private void Form1_Load(object sender, EventArgs e) { updateFileListlabel(); updateStatusLabel(); StatusLabel2.Text = ""; //测试读写set.ini文件的代码 //string value = Ini.readini("group1", "source", "default_value1", ".\\set.ini"); //Ini.writeini("group2", "key2", value, ".\\set.ini"); InitializeSets(); } private void InitializeSets() { textBoxSource.Text = Ini.readini("group1", "source", "I:\\backup", ".\\set.ini"); textBoxDestiny.Text = Ini.readini("group1", "destiny", "D:\\backup", ".\\set.ini"); checkBoxDel.Checked = Convert.ToBoolean(Ini.readini("group1", "deleteChecked", "true", ".\\set.ini")); DaysNumericUpDown.Value = Convert.ToDecimal(Ini.readini("group1", "days", "3", ".\\set.ini")); dateTimePicker1.Value = Convert.ToDateTime(Ini.readini("group1", "actionTime", "20:00:00", ".\\set.ini")); } private void updateStatusLabel() { StatusLabel1.Text="备份时间:"+dateTimePicker1.Value.ToShortTimeString(); } //刷新N天前文件列表标签 private void updateFileListlabel() { FileListlabel.Text = DaysNumericUpDown.Value + "天前的文件列表:"; } //更改天数时,刷新N天前文件列表标签 private void numericUpDown1_ValueChanged(object sender, EventArgs e) { updateFileListlabel(); Ini.writeini("group1", "days", DaysNumericUpDown.Value.ToString(), ".\\set.ini"); } private void buttonUpdateTodayFileList_Click(object sender, EventArgs e) { //清空列表 TodayFileslistBox.Items.Clear(); ArrayList filelist = fo.getFileList(textBoxSource.Text.Trim(),"==",0); mylistbox.showFilesList(filelist,TodayFileslistBox); } private void buttonUpdateNdaysFileList_Click(object sender, EventArgs e) { #region 模块化的代码,没用 //FillListBox(NdaysBeforeFilesListBox, textBoxDestiny.Text.Trim(), NdayBeforeFileslabel,Convert.ToInt16(DaysNumericUpDown.Value),"<="); #endregion fillNdaysListBox(); } private void fillNdaysListBox() { NdaysBeforeFilesListBox.Items.Clear(); ArrayList filelist = fo.getFileList(textBoxDestiny.Text.Trim(), "=>", Convert.ToInt16(DaysNumericUpDown.Value)); mylistbox.showFilesList(filelist, NdaysBeforeFilesListBox); } private void timer1_Tick(object sender, EventArgs e) { #region MyRegion if (DateTime.Now.ToShortTimeString() == dateTimePicker1.Value.ToShortTimeString()) { //显示今天文件在列表框 TodayFileslistBox.Items.Clear(); mylistbox.showFilesList(fo.getFileList(textBoxSource.Text.Trim(), "==", 0), TodayFileslistBox); //拷贝文件 if (TodayFileslistBox.Items != null) //如果没有当天的文件可复制,刚不删除旧已备份的文件 { for (int i = 0; i < TodayFileslistBox.Items.Count; i++) { string strName = TodayFileslistBox.Items[i].ToString().Substring(TodayFileslistBox.Items[i].ToString().LastIndexOf("\\")); try { StatusLabel2.Text = "正在复制文件:" + strName; fo.CopyFiles(TodayFileslistBox.Items[i].ToString(), textBoxDestiny.Text + strName); StatusLabel2.Text = strName+ " 复制完成"; lw.writeLog(TodayFileslistBox.Items[i].ToString() + " 复制成功");//写入日志文件 //以上代码跟“拷贝文件”按钮的代码有重复,之所以不能重构成方法,是因为下面两行Timer1代码包含了删除过期文件的代码。 //暂时没找到更好的方法,以后学习到更好的方法再改正。也希望同学们不吝赐教。 } catch (Exception ex) { StatusLabel2.Text = "备份过程出错,请查看日志文件Log.txt"; lw.writeLog(ex.ToString()); } }
//如果没有当天的文件可复制,刚不删除旧已备份的文件
//显示N天前的文件在列表框
fillNdaysListBox();
//删除文件
delfiles();
} #endregion } } private void buttonDelete_Click(object sender, EventArgs e) { if (MessageBox.Show("你确定要删除文件吗,删除后不可恢复!!","确定删除!!",MessageBoxButtons.YesNoCancel,MessageBoxIcon.Warning,MessageBoxDefaultButton.Button3) == DialogResult.Yes) { if (MessageBox.Show("确定要删!,不可恢复哦!!", "真的要删除!!", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button3) == DialogResult.Yes) { fillNdaysListBox(); delfiles(); } } } private void delfiles() { if (checkBoxDel.Checked) { for (int i = 0; i < NdaysBeforeFilesListBox.Items.Count; i++) { string path = NdaysBeforeFilesListBox.Items[i].ToString(); try { fo.DeleteFiles(path); StatusLabel2.Text = path + " 删除成功"; lw.writeLog(path + " 删除成功"); } catch (Exception e) { StatusLabel2.Text = path + " 删除失败,请查看日志文件!"; lw.writeLog(e.ToString()); } } } } private void dateTimePicker1_ValueChanged(object sender, EventArgs e) { updateStatusLabel(); Ini.writeini("group1", "actionTime", dateTimePicker1.Value.ToShortTimeString(), ".\\set.ini"); } private void textBoxSource_TextChanged(object sender, EventArgs e) { Ini.writeini("group1", "source", textBoxSource.Text.Trim() , ".\\set.ini"); } private void textBoxDestiny_TextChanged(object sender, EventArgs e) { Ini.writeini("group1", "destiny", textBoxDestiny.Text.Trim(), ".\\set.ini"); } private void checkBoxDel_CheckedChanged(object sender, EventArgs e) { Ini.writeini("group1", "deleteChecked", checkBoxDel.Checked.ToString(), ".\\set.ini"); } } }