C#读取文件元数据 C#如何获取文件的任意元数据属性

来源:这里教程网 时间:2026-02-21 17:42:14 作者:

Shell32.Shell
读取 Windows 文件任意属性(如“作者”“标签”“相机型号”)

Windows 资源管理器里右键 → “属性” → “详细信息”页签能看到的那些字段,C# 默认的

FileInfo
File.GetAttributes()
根本拿不到。真正能访问这些 Shell 层元数据的,是 COM 组件
Shell32.Shell
,它暴露了底层 Property System 的接口。

实操要点:

必须引用
Shell32
COM 库(项目 → 添加引用 → 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 初始化失败、权限拒绝、路径不存在这些异常。没人能靠一个方法通吃,关键在分清“这个属性到底存在哪一层”。

相关推荐