制作物はこちら
はじめに
Windowsの標準エクスプローラでは、詳細表示の状態であっても、フォルダのサイズが一覧表示されることはありません。そのため、フォルダサイズの大きいものから整理したいときなどはpowershellスクリプトを実行するか、サードパーティー製のツールをインストールして起動する必要があります。しかし、いずれの方法も、フォルダを整理したい目的に対して手軽さが不足しています。
そこで本稿では、標準エクスプローラのサイズ列にフォルダサイズを直接表示し、既存のアプリケーションに手を加えることなく機能を拡張することを試みました。
実装概要
サイズ列に透明のウィンドウを作成し、
各フォルダの「サイズ」欄にフォルダサイズを表示することで、
標準エクスプローラで違和感のないふるまいをすると考えました。
主に以下を軸にしてC#の.NET8で実装しました。
- フォルダサイズは、その配下にある全ファイルのサイズの合計
- エクスプローラのサイズ列の位置は、UIAutomationを用いて取得
サイズ列の取得方法は手動で探しました。以下のようなコードを実行することでエクスプローラの要素をすべて列挙することができます。
var explorerWindows = AutomationElement.RootElement.FindAll(
TreeScope.Children,
// エクスプローラはCabinetWClass
new PropertyCondition(AutomationElement.ClassNameProperty, "CabinetWClass")
);
foreach (var window in explorerWindows)
{
var allElements = window.FindAll(
TreeScope.Descendants, Condition.TrueCondition
);
foreach (var element in allElements)
{
string name = element.Current.Name;
ControlType type = element.Current.ControlType;
string id = element.Current.AutomationId;
// コンソールに出力(コンソールアプリなど)
Console.WriteLine($"Name: {name}, ControlType: {type.ProgrammaticName}, AutomationId: {id}");
// txtに出力する(Windowsアプリなど)
File.AppendAllText(@"C:\Users\result.txt", $"Name: {name}, ControlType: {type.ProgrammaticName}, AutomationId: {id}" + Environment.NewLine);
}
}
その結果次のようなテキストが得られました。これよりサイズ列は
ControlType == ControlType.Edit, AutomationId == "System.Size"
であることがわかったので、これを条件にサイズ列の位置を取得することができました。
Name: main.c, ControlType: ControlType.ListItem, Id: 3
Name: 名前, ControlType: ControlType.Edit, Id: System.ItemNameDisplay
Name: 更新日時, ControlType: ControlType.Edit, Id: System.DateModified
Name: 種類, ControlType: ControlType.Edit, Id: System.ItemTypeText
Name: サイズ, ControlType: ControlType.Edit, Id: System.Size
動作イメージ
レジストリに本アプリケーションを登録して、実際に図1, 2の通り動作しました。
課題・今後の改善
スクロールすると再描画するようにしたのですが、激しくスクロールするとエクスプローラが応答なしになることがあります。
仕様としては、アプリケーションを起動した時点でフォルダと対応するサイズのペアを保持しているため、フォルダ内が変更されても反映することができません。
まとめ
フォルダサイズをエクスプローラのサイズ列に直接表示するアイデアが形になり、最低限の機能を実装できました。しかし、全体的に自分の知識が浅いため、アプリケーションとしては使いやすいものになりませんでした。
有識者の知見や改善案をいただけると幸いです。