C# 文件夹元数据编辑器






4.81/5 (28投票s)
使用 desktop.ini 功能编辑文件夹元数据
引言
当我想管理一堆文件夹而无需将其组织到子目录中时,出现了对文件夹元数据编辑器的需求。在网上搜索时,我发现 *desktop.ini*(以及 Windows 资源管理器)支持我正在寻找的功能——只是 Microsoft 没有提供用户界面。所以这就是文件夹元数据编辑器发挥作用的地方。它提供了一种编辑这些元数据的简单方法。
背景
*Desktop.ini* 支持文件夹的元数据,如果它包含以下内容
[{F29F85E0-4FF9-1068-AB91-08002B27B3D9}]
Prop2=31,Title
Prop3=31,Subject
Prop4=31,Author
Prop5=31,Tag
Prop6=31,Comment
为了读写,使用了 API 函数 `GetPrivateProfileString` 和 `WritePrivateProfileString`。
文件夹元数据编辑器还支持简单的参数解析和本地化。
Using the Code
代码分为以下子命名空间
- 配置
- 参数解析
- 本地化
- 注册
- 对话框
- 对话框表单
- 扩展的 `ListBox` 控件
- 表单帮助类和从资源中提取图标
- 扩展
- `string` 和 `StringCollection` 类的扩展
- Generic
- 加载/写入 *desktop.ini*
- 通用帮助类
配置
参数解析
参数解析由 `ArgParser` 类完成,该类使用 `ParameterNames` 类。
*ParameterNames.cs* 文件包含 `ParameterNames` 类和 `ParamConstants` 枚举。
`ParameterNames` 类的 `ParseParamConstants` 函数将诸如 */dir* 等命令行参数转换为适当的 `ParamConstants` 值 `ParamConstants.Dir`。
实际的参数解析是在 `ArgParser` 类中完成的。由于这是一个 `Windows.Forms` 应用程序,我们的 `main` 函数中没有 `string[] args` 参数。因此,`ArgParser` 类有一个无参数构造函数,并通过 `using System.Environment.GetCommandLineArgs()` 检索命令行参数。
注册
由于该应用程序应与文件夹一起使用,因此我们需要在 Windows 注册表的 *HKEY_CLASSES_ROOT\Folder\shell* 下注册它。为此,我们创建一个新的注册表项 `FolderMetaData`。此项的默认值表示快捷菜单中的文本(当在 Windows 资源管理器中右键单击文件夹时)。在此注册表项下,我们创建另一个注册表项 `command`。`command` 项的默认值然后包含应用程序的完整路径以及文件夹的路径,例如,*C:\Program Files\FolderMetadata\FolderMetadata.exe /dir "%1"*"。
为了允许在右键单击文件夹背景时使用应用程序,我们在 *HKEY_CLASSES_ROOT\Directory\Background\shell* 下创建另一个注册表项。过程与之前相同。唯一的区别是这里我们不使用 `%1` 作为参数,而是使用 `%V`。
取消注册时,通过检查 `command` 注册表项的默认值来识别注册表项。这允许即使使用不同语言创建了注册表项,也可以将其删除。
注册和取消注册由 `Registrator` 类完成。您需要管理权限才能成功执行这些操作。
在命令行上,使用以下命令注册或取消注册
- FolderMetadata.exe /register
- FolderMetadata.exe /unregister
本地化
本地化由 `LanguageConfigurator` 类处理。在大多数情况下,它只会使用其运行环境的语言。但是,您也可以通过指定 */lang* 命令行参数(例如,对于日语,`/lang ja`)或通过指定命令行参数 `/lang select` 来选择它来更改语言。为了让语言选择对话框显示所有支持的语言列表,`SupportedLanguages` 类的 `GetSupportedLanguages` 函数必须包含它。
如果您处理字母语言,`Windows.Forms` 应用程序的本地化非常简单。当处理非字母语言(例如中文和日语)时,这会变得更具挑战性。
- 速记符支持(按钮的键盘快捷键,例如 `&Save`)将不存在
- 处理简体和繁体中文本地化
由于我想保持本地化过程简单,我将大部分工作留给了 .NET Framework。因此,我将 `FolderMetadata` 项目的 `Neutral language` 属性设置为“`English (United States)`”。并创建了一个单独的资源文件 *Strings.resx*。此文件包含所有翻译 + 值 `ForceMnemonics`,它表示一个 `bool` 值,并且 **必须** 是 `true` 或 `false`。解析结果可在 `LanguageConfigurator` 类的 `ForceShowMnemonics` 属性中访问。
对于中文本地化,我创建了两个资源文件
- Strings.zh.resx
- Strings.zh-TW.resx
这意味着所有用户(除了那些使用台湾 Windows 设置的用户)都会看到简体中文字符。但是,这不适用于来自香港和澳门的用户。所以我添加了函数 `GetLanguageZH`,它检查语言设置是否需要显示繁体中文。如果需要,它会将语言设置更改为 `zh-TW`。现在用户也可以看到繁体中文字符了。
对话框
翻译对话框
当表单复杂时,设置表单的 `Localizable` 和 `Language` 属性可能是一个好方法。这允许例如为每种语言重新排列控件。但是,如果您有许多语言,这会使编辑对话框变得更加困难。这就是我决定不采用这种方法并采用更实用的方法的原因:使用 `TableLayoutPanel` 和支持类 `ButtonAdjustor` 使按钮具有相同的宽度。
每个表单都有一个 `WndProc` 重写。在这个重写函数中,我们检查 `LanguageConfigurator` 类的 `ForceShowMnemonics` 属性是否为 `true`。如果是,它将调用 `WndProcOverrides` 类的 `ShowMnemonics` 方法,该方法确保助记符可见。
帮助
表单 `FrmHelp` 包含 HTML 格式的帮助。它也被翻译成各种语言,并在用户执行以下操作之一时打开
- 不指定任何支持的参数启动应用程序(例如,在 Windows 资源管理器中双击)
- 指定 `/?` 命令行参数
控件
`ListBoxEx 控件` 继承自 `Windows.Forms` 的 `ListBox`。它提供了一些用于加载值(在 `FrmMain` 表单上使用)和移动选定项(在 `FrmManage` 表单上使用)的函数。
扩展
如果您之前没有使用过扩展,那么您错过了一个非常有用的 .NET 功能。扩展允许您将自己的函数添加到类中。只有一个缺点:您只能添加实例函数,而不能添加 `static` 函数,例如 `string.IsNullOrEmpty`。
定义
public static class String
{
public static bool IsEmpty(this string s)
{
return (s.Length == 0);
}
}
用法
using HKS.FolderMetadata.Extensions; //Add this on top of your class file,
//preceding the name space definition.
//In your method, use something like this:
string s = "Hello";
if (s.IsEmpty())
{
//Do something
}
Generic
读写 Desktop.ini
读写 *desktop.ini* 的功能在 `Metadata` 类中。由于此程序旨在用于 Windows 平台,我们可以使用 API 函数 `GetPrivateProfileString` 和 `WritePrivateProfileString` 进行读写。
在 *desktop.ini* 中,所有元数据属性都是单行文本。由于可能不止一个人是作者(例如,披头士的歌曲总是由约翰·列侬和保罗·麦卡特尼创作),或者您想设置多个标签,我们必须将单行转换为列表,反之亦然。
`Metadata` 类的构造函数期望要编辑元数据的目录的完整路径。然后它将组装 *desktop.ini* 的完整路径。该类具有由 `Load` 方法填充并通过 `Save` 方法写入文件的属性。
历史
- 2021年1月3日
- 首次发布
- 2021年7月15日
- 版本 1.0.1
- 修复了内存异常
- 版本 1.0.1
- 2024年2月24日
- 版本 2.0.0
- 允许右键单击文件夹背景以启动应用程序
- 为快捷菜单添加了图标
- 版本 2.0.0