getfileinformationbyhandle无法获取作者、标题等shell属性,需用com接口ipropertystore配合coinit_apartmentthreaded初始化,通过pkey_author等propertykey读取,并注意propvariant内存管理与格式兼容性。

用 GetFileInformationByHandle 只能拿到基础时间/大小,拿不到作者、标题
Windows 文件的作者、标题这类信息属于「NTFS 替换数据流(ADS)中的属性集」或「Shell 属性系统(Property System)」,不是传统文件系统元数据。直接调用 GetFileInformationByHandle 或 FindFirstFile 返回的 WIN32_FIND_DATA 结构体里压根没有这些字段——它们根本不在 NTFS MFT 记录里,而是由 Windows Shell(explorer.exe)在读取时动态解析文件内容(如 DOCX 的 XML、MP3 的 ID3、JPEG 的 EXIF/XMP)或从 SummaryInformation / DocumentSummaryInformation 这类 OLE 复合文档流中提取的。
所以第一步必须绕过底层句柄 API,转向 COM 接口:IPropertyStore + SHGetPropertyStoreFromIDList 或 SHGetPropertyStoreFromParsingName。
必须初始化 COM,且只能用 COINIT_APARTMENTTHREADED
所有 Property System 相关接口都运行在 STA(单线程单元)下,如果用 COINIT_MULTITHREADED 初始化,后续调用 GetValue 会静默失败或返回 TYPE_E_TYPEMISMATCH —— 这是 C++ 开发者最常卡住的地方,错误不报异常,只返回失败码,还容易误判成路径错或权限问题。
实操建议:
- 在
main()或线程入口处第一时间调用CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED),别漏掉 - 记得配对调用
CoUninitialize(),否则多次运行可能触发 COM 内部资源泄漏 - 不要在 DLL 的
DllMain里初始化 COM —— Windows 不允许
用 PSGetPropertyDescription 查属性名对应的 PROPERTYKEY
“作者”“标题”这些中文名不能直接当参数传,Property System 用的是全局唯一的 PROPERTYKEY(比如 PKEY_Author、PKEY_Title)。硬编码 GUID 很容易写错,推荐用 Windows SDK 提供的头文件宏:
#include <propsys.h> #include <propkey.h> // 正确:用宏,不是自己拼 GUID PROPERTYKEY key = PKEY_Author;</propkey.h></propsys.h>
常见坑:
- 忘记链接
Propsys.lib和Shlwapi.lib,链接时报LNK2019: unresolved external symbol - 用
PKEY_ItemNameDisplay代替PKEY_Title—— 前者是 shell 显示名(可能含扩展名),后者才是文档元数据里的 Title 字段 - 对非 Office/媒体文件(比如纯 TXT),
PKEY_Author通常为空,这不是 bug,是文件本身没嵌入该属性
调用 IPropertyStore::GetValue 后要手动释放 PROPVARIANT
GetValue 把结果写进 PROPVARIANT,但类型可能是 VT_LPWSTR、VT_FILETIME 甚至 VT_VECTOR | VT_UI1(二进制数据)。如果只取字符串却忘了判断 v.vt == VT_LPWSTR,直接 wprintf 会崩;如果值是 VT_LPWSTR 却没调用 PropVariantClear(&v),会导致内存泄漏(COM 分配的堆内存)。
安全写法要点:
- 总是先检查
v.vt,再分支处理;不要假设一定是字符串 - 所有分支末尾加
PropVariantClear(&v),哪怕只读一个属性也得清 - 对
VT_LPWSTR,用wcscpy_s拷贝前确认v.pwszVal != nullptr
复杂点在于不同文件格式支持的属性差异极大:DOCX 能读全,TXT 基本为空,PNG 可能只有 PKEY_Image_DateTaken —— 没统一规律,得按需试。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











