いざというときに役にたつのがバックアップ。大切なファイルを間違って削除してしまった、上書きしてしまった。こんなときにバックアップをしていると最悪の事態を回避することができます。
でもこのバックアップ、地味に面倒くさい作業でもあります。そこでクリック一発でバックアップができるアプリを作成してみました。
事前にバックアップしたいフォルダとバックアップ先を登録しておきます。あとはクリックするだけでバックアップしてくれます。
バックアップしたいフォルダとバックアップ先の登録はTextBoxに入力するのですが、簡単にできるように以下のようなクラスをつくってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
public class TextBoxForFilePath : TextBox { public TextBoxForFilePath() { AllowDrop = true; } protected override void OnDragOver(DragEventArgs e) { base.OnDragOver(e); if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Copy; } protected override void OnDragDrop(DragEventArgs e) { base.OnDragOver(e); if (e.Data.GetDataPresent(DataFormats.FileDrop)) { string[] vs = (string [])e.Data.GetData(DataFormats.FileDrop); Text = vs[0]; } } protected override void OnKeyDown(KeyEventArgs e) { if (e.KeyCode == Keys.V && e.Control) { if(Clipboard.ContainsFileDropList()) { var paths = Clipboard.GetFileDropList(); Text = paths[0]; e.Handled = true; e.SuppressKeyPress = true; return; } } base.OnKeyDown(e); } } |
手作業で入力するのは面倒なので、ファイルやフォルダをドラッグ&ドロップすればパスが入力されます。またファイルやフォルダをコピーしてペーストしてもパスを入力することができます。
バックアップするフォルダとバックアップ先が決まれば、あとはファイルを圧縮して保存するだけです。
Zipファイルの作成はこのページを参考にしました。
やることはSystem.IO.Compression.FileSystem.dllを参照に追加。
あとは
1 2 3 4 5 |
using System.IO.Compression; string sourceFolderPath = @"E:\Test"; string zipFilePath = @"E:\Test.zip"; ZipFile.CreateFromDirectory(sourceFolderPath, zipFilePath); |
これでOK♪
さてバックアップといってもいらないファイルもあるはずです。そのようなものは除外したいものです。Zipファイルが無意味に大きくなるだけですから。
そこでどうするか?
System.IO.Compression.FileSystemにくわえてSystem.IO.Compressionも参照に追加します。
まずフォルダのなかのファイルパスのみ取得します。
そして・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
string sourceFolderPath = @"E:\Test"; string zipFilePath = @"E:\Test.zip"; string[] paths = Directory.GetFiles(sourceFolderPath, "*.*", SearchOption.AllDirectories); using (var z = ZipFile.Open(backupPath, ZipArchiveMode.Update)) { foreach (string filePath in paths) { string filePath0 = filePath; if(いらないファイル) continue; string fileName = filePath0.Replace(folderPath + "\\", ""); z.CreateEntryFromFile(filePath, fileName, CompressionLevel.Optimal); } } |
これで必要なファイルだけバックアップすることができます。
設定を保存できるようにする
毎回、ファイルパスを入力するのは面倒なので、登録したフォルダパスは保存できるようにしましょう。
まずアプリの外観はこんな感じ。
[登録]をクリックするとこのようなダイアログが表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
public partial class Form1 : Form { private void buttonRegist_Click(object sender, EventArgs e) { RegistItem(); } void RegistItem() { Form2 form2 = new Form2(); if (form2.ShowDialog() == DialogResult.OK) { string backupSource = form2.textBoxExBackupSource.Text; string backupTardet = form2.textBoxExBackupTarget.Text; string exeptExt = form2.textBoxExeptExtension.Text; if (Directory.Exists(backupSource) && Directory.Exists(backupTardet)) { Datas.Add(new Data(backupSource, backupTardet, exeptExt)); listView1.Items.Clear(); foreach (Data data in Datas) { ListViewItem item = new ListViewItem(data.GetData(), 0); listView1.Items.Add(item); } } SavaConfigFile(); } } List<Data> Datas = new List<Data>(); public class Data { public string SourceFolderPath = ""; public string BackupFolderPath = ""; public string ExeptExtension = ""; public Data() { } public Data(string s1, string s2, string s3) { SourceFolderPath = s1; BackupFolderPath = s2; ExeptExtension = s3; } public string[] GetData() { var ss = new string[3]; ss[0] = SourceFolderPath; ss[1] = BackupFolderPath; ss[2] = ExeptExtension; return ss; } } } |
登録ボタンをおしたらフィールド変数Datasにデータを格納するとともにファイルとして保存してしまいましょう。そのために作成したのがSavaConfigFileです。実行ファイルがあるフォルダ内にファイルをつくります。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class Form1 : Form { void SavaConfigFile() { XmlSerializer xml = new XmlSerializer(typeof(List<Data>)); string filePath = Application.StartupPath + "\\config.cfg"; StreamWriter sw = new StreamWriter(filePath); xml.Serialize(sw, Datas); sw.Close(); } } |
アプリケーションが実行されたらファイルを読み取ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { private void Form1_Load(object sender, EventArgs e) { XmlSerializer xml = new XmlSerializer(typeof(List<Data>)); string filePath = Application.StartupPath + "\\config.cfg"; if (!File.Exists(filePath)) return; StreamReader sr = new StreamReader(filePath); Datas = (List<Data>)xml.Deserialize(sr); sr.Close(); listView1.Items.Clear(); columnHeader1.Width = 300; columnHeader2.Width = 300; foreach (Data data in Datas) { ListViewItem item = new ListViewItem(data.GetData(), 0); listView1.Items.Add(item); } } } |
使わない項目は削除できるようにしてしまいましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
public partial class Form1 : Form { void DeleteItems() { var indexes = listView1.SelectedIndices; List<int> vs = new List<int>(); foreach (int i in indexes) vs.Add(i); var indexes1 = vs.OrderByDescending(x => x); foreach (int i in indexes1) Datas.RemoveAt(i); listView1.Items.Clear(); foreach (Data data in Datas) { ListViewItem item = new ListViewItem(data.GetData(), 0); listView1.Items.Add(item); } SavaConfigFile(); } } |
リストビューのアイテムがクリックされたら選択された部分の設定情報を表示させます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
public partial class Form1 : Form { private void listView1_SelectedIndexChanged(object sender, EventArgs e) { var indexes = listView1.SelectedIndices; if (indexes.Count == 1) { int i = indexes[0]; string backupSourceFolder = Datas[i].SourceFolderPath; string backupTargetFolder = Datas[i].BackupFolderPath; string exeptExtension = Datas[i].ExeptExtension; labelBackupSourceFolder.Text = backupSourceFolder; labelBackupTargetFolder.Text = backupTargetFolder; labelExeptExtension.Text = exeptExtension; } else { labelBackupSourceFolder.Text = ""; labelBackupTargetFolder.Text = ""; labelExeptExtension.Text = ""; } } } |
リストビューの項目にチェックをいれて実行ボタンがおされたらバックアップを開始します。指定された拡張子のファイルはバックアップの対象外となります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
public partial class Form1 : Form { void DoBackupFolders() { List<int> vs = new List<int>(); foreach (int i in listView1.CheckedIndices) vs.Add(i); var indexes1 = vs.OrderBy(x => x); foreach (int i in indexes1) { listView1.Items[i].Selected = true; if (!Directory.Exists(Datas[i].BackupFolderPath)) { errers.Add(String.Format("{0}は存在しない", Datas[i].BackupFolderPath)); continue; } if (!Directory.Exists(Datas[i].SourceFolderPath)) { errers.Add(String.Format("{0}は存在しない", Datas[i].SourceFolderPath)); continue; } // Zipファイルのパス DateTime dt = DateTime.Now; string str = dt.ToString("yyyy-MMdd-HHmmss"); string sourceFolderPath = Datas[i].SourceFolderPath; DirectoryInfo info = new DirectoryInfo(sourceFolderPath); string name = info.Name; string backupPath = String.Format("{0}\\{1}-{2}.zip", Datas[i].BackupFolderPath, name, str); DoBackup(sourceFolderPath, backupPath, Datas[i].ExeptExtension); System.Threading.Thread.Sleep(1000); } MessageBox.Show("完了しました"); } void DoBackup(string sourceFolderPath, string backupPath, string exeptExtension) { string[] paths = Directory.GetFiles(sourceFolderPath, "*.*", SearchOption.AllDirectories); string[] exeptExtensions = exeptExtension.ToLowerInvariant().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); using (var z = ZipFile.Open(backupPath, ZipArchiveMode.Update)) { foreach (string filePath in paths) { string filePath0 = filePath; FileInfo info = new FileInfo(filePath0); string ext = info.Extension; ext = ext.Replace(".", "").ToLowerInvariant(); if (exeptExtensions.Any(x => x == ext)) continue; string fileName = filePath0.Replace(sourceFolderPath + "\\", ""); z.CreateEntryFromFile(filePath, fileName, CompressionLevel.Optimal); } } } } |
バックアップをするときのファイル名はわかりやすくするためにフォルダ名とバックアップ時刻をいれるようにしています。