shell32.shell可读取windows文件任意shell属性(如authors、system.photo.cameramodel),需引用com库并用绝对路径;system.drawing.image仅支持图像exif基础元数据;windows.storage.fileproperties适用于uwp/msix应用;taglib#专注音视频标准标签,跨平台但不支持文档或shell自定义属性。

用 Shell32.Shell 读取 Windows 文件任意属性(如“作者”“标签”“相机型号”)
Windows 资源管理器里右键 → “属性” → “详细信息”页签能看到的那些字段,C# 默认的 FileInfo 或 File.GetAttributes() 根本拿不到。真正能访问这些 Shell 层元数据的,是 COM 组件 Shell32.Shell,它暴露了底层 Property System 的接口。
实操要点:
- 必须引用
Shell32COM 库(项目 → 添加引用 → COM → “Microsoft Shell Controls And Automation”) - 路径要用完整绝对路径,相对路径或 UNC 路径可能失败
- 不是所有文件类型都支持全部属性;比如 .txt 文件没有
CameraModel,但会返回空字符串而非抛异常 - 属性名是字符串,大小写敏感,常见值如
"Authors"、"System.Keywords"、"System.Photo.CameraModel"
var shell = new Shell32.Shell();
var folder = shell.NameSpace(Path.GetDirectoryName(filePath));
var file = folder.ParseName(Path.GetFileName(filePath));
string author = folder.GetDetailsOf(file, folder.GetDetailsOf(null, 0).IndexOf("Authors"));
System.Drawing.Image 只能读图片基础元数据(尺寸、EXIF、GPS)
如果只是处理 JPG/PNG 等图像,且只关心宽高、拍摄时间、经纬度这类标准 EXIF 或 XMP 数据,System.Drawing.Image 更轻量、无需 COM、跨平台兼容性略好(.NET Core 3.1+ 支持部分)。
但它有硬限制:
- 不支持非图像文件(PDF、DOCX、MP4 都不行)
- 无法读取 Windows Shell 扩展属性(如“标签”“评级”“作者”等自定义字段)
- EXIF 解析依赖 GDI+,某些嵌套结构(如 MakerNote)可能被忽略或解析错误
- .NET 6+ 中
System.Drawing在 Linux/macOS 上需额外安装 libgdiplus,且部分 EXIF 标签映射不一致
using var img = Image.FromFile("photo.jpg");
var propItems = img.PropertyItems; // 返回 byte[] 数组,需手动 decode用 Windows.Storage.FileProperties(UWP/WinRT API)获取现代属性,但仅限 UWP 或桌面桥接
如果你在开发 UWP 应用,或通过 Desktop Bridge(如打包成 MSIX)运行桌面程序,Windows.Storage.FileProperties 是最干净的方式:异步、强类型、支持所有 Shell 属性,还带缓存和权限控制。
但注意现实约束:
- 桌面 .NET Framework / .NET 5+ 直接引用会报错,必须启用“Windows SDK”并添加
Windows.Foundation.UniversalApiContract引用 - 需要用户授予“文件系统”能力(manifest 中声明
uap:Capability),否则运行时拒绝访问 - 对网络驱动器、加密卷、符号链接支持不稳定,容易抛
UnauthorizedAccessException - 属性名用
System.前缀统一,例如System.Author、System.Keywords,比 Shell32 的字符串名更规范
var file = await StorageFile.GetFileFromPathAsync(filePath);
var props = await file.Properties.RetrievePropertiesAsync(new[] { "System.Author", "System.Keywords" });为什么不用 TagLib#?它适合什么场景
TagLib# 是开源音频/视频/图片元数据库,擅长 MP3 ID3、FLAC Vorbis、MP4 atoms、JPEG IPTC 这类标准媒体标签。它不依赖 Windows COM,纯托管,跨平台,解析精度高。
但它不是通用方案:
- 对 Office 文档(.docx/.xlsx)、PDF、普通文本完全无支持
- Windows Shell 自定义属性(比如你在资源管理器里右键填的“标签”)它根本看不到
- 某些厂商私有 EXIF(如索尼 ARW、佳能 CR2 的 MakerNote)支持有限,需手动注册 handler
- 新版 .NET 6+ 中需确认是否已适配
System.IO.Pipelines,否则大文件流式读取可能卡顿
using var file = TagLib.File.Create("song.mp3");
string title = file.Tag.Title; // 安全,有 fallback真正麻烦的是混合场景:一个目录里既有照片、又有 Word 报告、还有会议录音。这时候得按文件扩展名分流处理——Shell32 处理通用文档,TagLib# 处理音视频,Image 处理缩略图,还要兜底捕获 COM 初始化失败、权限拒绝、路径不存在这些异常。没人能靠一个方法通吃,关键在分清“这个属性到底存在哪一层”。










