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"); } } }