このアプリケーションはリアルタイムでファイル構造を監視しているわけではありません。そのため別のアプリでファイルが削除されたりフォルダ名が変更されたときに対応できない場合があります。そこでリンク切れになってしまった場合、これを探しだし修正する機能を追加します。
リストボックスにリンク切れになっているパスの一覧が表示されます。また登録されている古いパスを新しいパスに修正することもできるようにしています。
まずメニュー[操作] ⇒ [リンク切れチェック]を選択するとFileTagsに格納されているデータのなかから存在しないパスを探し出し、それを上記のフォームのリストボックスに一覧として表示します。
1 2 3 4 5 6 7 8 9 10 11 12 |
public partial class Form1 : Form { private void MenuItemCheckLink_Click(object sender, EventArgs e) { SaveOldData(); List<FileTag> fileTag = FileTags.Where(x => !File.Exists(x.FilePath) && !Directory.Exists(x.FilePath)).ToList(); FormBrokenLink f = new FormBrokenLink(); f.BrokenLinks = fileTag.Select(x => x.FilePath).ToList(); f.Show(this); } } |
リンク切れ一覧を表示するフォームです。ダイアログが表示されるときにリンク切れの一覧が表示されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public partial class FormBrokenLink : Form { public FormBrokenLink() { InitializeComponent(); buttonCopyPath.Click += ButtonCopyPath_Click; buttonReplacePath.Click += ButtonReplacePath_Click; } public List<string> BrokenLinks = null; private void FormLinkCloth_Load(object sender, EventArgs e) { foreach(string path in BrokenLinks) listBox1.Items.Add(path); } } |
リンク切れになる原因として、ファイル等の名前の変更や削除があります。フォルダ名を変更した場合、それまで登録していたファイルの多くがリンク切れになることが考えられます。この場合はまとめてフォルダパスを書き換えればリンク切れも解消するので、一括処理ができるようにしました。
置換前のパスは手作業で入力しなくてもよいように、リストボックスで選択されているパスをそのままテキストボックスにコピーできるようにしています。
1 2 3 4 5 6 7 8 9 10 11 |
public partial class FormBrokenLink : Form { private void ButtonCopyPath_Click(object sender, EventArgs e) { int index = listBox1.SelectedIndex; if(index != -1) { textBox1.Text = (string)listBox1.Items[index]; } } } |
以下は[パスの置換を実行する]ボタンがクリックされたときの処理です。
置換するときに、C:\新しいフォルダ ⇒ C:\新しいフォルダその2のようにフルパスを入力する必要はありません。新しいフォルダ ⇒ 新しいフォルダその2のように一部だけ指定することもできます。また設定ミスで存在しないパスに置換しても意味がないので、実際にファイル等が存在するときだけデータを書き換えるようにしています。
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 |
public partial class FormBrokenLink : Form { private void ButtonReplacePath_Click(object sender, EventArgs e) { if(textBox1.Text == "") { MessageBox.Show("置換元の文字列が入力されていません!", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } Form1 f = (Form1)this.Owner; List<FileTag> tags = f.FileTags.Where(x => x.FilePath.IndexOf(textBox1.Text) != -1).ToList(); List<string> brokenLinks = new List<string>(); foreach(string str in BrokenLinks) { string path = str; path = path.Replace(textBox1.Text, textBox2.Text); // 置換後のパスは存在するのか? 存在しない場合は無視 if(File.Exists(path) || Directory.Exists(path)) { FileTag tag = tags.FirstOrDefault(x => x.FilePath == str); if(tag != null) tag.FilePath = path; } else brokenLinks.Add(str); // 処理後もリンク切れのままのもの } // リンク切れとしてリストボックスに表示するものを更新する BrokenLinks = brokenLinks; listBox1.Items.Clear(); foreach(string path in BrokenLinks) listBox1.Items.Add(path); } } |
このアプリケーションを使用中にフォルダ名が変更される場合をこれまで想定していませんでしたが、実際にはありうるので対応できるようにしておかないといけません。トラブルが起きるとすれば
リストビューで選択されているアイテムが変更されたとき
リストビューのアイテムがダブルクリックされたとき
[上へ]ボタンが押されたとき
このときに
フォルダ名の変更によって現在のパスがすでに存在しない
移動先のフォルダが存在しない
参照すべきファイル等が存在しない
などが考えられます。
この場合はそのドライブのルートディレクトリに移動します。
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 67 68 69 70 71 72 73 74 |
public partial class Form1 : Form { bool MoveRootIfNotExistCurFolder() { if(!Directory.Exists(CurFolderPath)) { MessageBox.Show("フォルダパスが変更されています。ルートフォルダに移動します。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); DirectoryInfo info = new DirectoryInfo(CurFolderPath); MoveRootFolder(info.Root.FullName); return true; } return false; } private void listView1_DoubleClick(object sender, EventArgs e) { // CurFolderPathが存在しない場合はルートフォルダへ移動 if(MoveRootIfNotExistCurFolder()) return; var sels = listView1.SelectedItems; string newPath = CurFolderPath + "\\" + sels[0].Text; if(Directory.Exists(newPath)) MoveToFolder(newPath); else if(File.Exists(newPath)) OpenFile(newPath); else { // 移動先が存在しないとき MessageBox.Show("フォルダまたはファイル名が変更されています。\n現在のフォルダ内容を表示します。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); MoveToFolder(CurFolderPath); } } void MoveToParentFolder() { // CurFolderPathが存在しない場合はルートフォルダへ移動 if(MoveRootIfNotExistCurFolder()) return; DirectoryInfo info = new DirectoryInfo(CurFolderPath); if(info == null || info.Parent == null) return; MoveToFolder(info.Parent.FullName); } private void listView1_SelectedIndexChanged(object sender, EventArgs e) { // CurFolderPathが存在しない場合はルートフォルダへ移動 if(MoveRootIfNotExistCurFolder()) return; var selItems = listView1.SelectedItems; if(selItems.Count == 0) return; string newPath; if(CurFolderPath.EndsWith("\\")) newPath = CurFolderPath + selItems[0].Text; else newPath = CurFolderPath + "\\" + selItems[0].Text; if(File.Exists(newPath) || Directory.Exists(newPath)) SelectedPath = newPath; else { // newPathが存在しないとき MessageBox.Show("フォルダまたはファイル名が変更されています。\n現在のフォルダ内容を表示します。", "エラー", MessageBoxButtons.OK, MessageBoxIcon.Error); MoveToFolder(CurFolderPath); } } } |