如何使用C++获取文件详情标签的全部扩展属性?
在C++中获取文件详情标签的所有属性及值
当然可以!你提到的GetFileAttributes()、GetFileAttributesEx()以及WIN32_FIND_DATA这些API,只能获取文件系统层面的基础属性(比如只读、压缩、创建时间、文件大小),但文件详情标签里的大部分属性(比如文档作者、音乐流派、图片分辨率、视频时长这类)属于Windows Shell范畴的属性,需要用到Shell相关的COM API来获取。
核心思路:使用Shell的IShellItem2和IPropertyStore接口
Windows Shell提供了专门的属性系统来管理这些扩展属性,核心是IShellItem2接口(用于获取单个属性)和IPropertyStore接口(用于枚举所有属性)。
代码示例:获取指定文件的多个Shell属性
以下是一个完整的示例,展示如何获取文件的常见详情属性:
#include <windows.h> #include <shobjidl.h> #include <propsys.h> #include <propkey.h> #include <iostream> #include <string> #pragma comment(lib, "shell32.lib") #pragma comment(lib, "propsys.lib") void PrintPropertyValue(IShellItem2* pItem, REFPROPERTYKEY propKey) { PROPVARIANT propVar; PropVariantInit(&propVar); if (SUCCEEDED(pItem->GetProperty(propKey, &propVar))) { // 根据属性类型处理值 switch (propVar.vt) { case VT_LPWSTR: std::wcout << L"Value: " << propVar.pwszVal << std::endl; break; case VT_FILETIME: { SYSTEMTIME st; FileTimeToSystemTime(&propVar.filetime, &st); std::wcout << L"Value: " << st.wYear << L"/" << st.wMonth << L"/" << st.wDay << L" " << st.wHour << L":" << st.wMinute << std::endl; break; } case VT_UI4: std::wcout << L"Value: " << propVar.uiVal << std::endl; break; case VT_BOOL: std::wcout << L"Value: " << (propVar.boolVal ? L"True" : L"False") << std::endl; break; default: std::wcout << L"Unsupported property type: " << propVar.vt << std::endl; break; } PropVariantClear(&propVar); } else { std::wcout << L"Failed to get property value" << std::endl; } } int wmain(int argc, wchar_t* argv[]) { if (argc != 2) { std::wcout << L"Usage: " << argv[0] << L" <file path>" << std::endl; return 1; } // 初始化COM HRESULT hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); if (FAILED(hr)) { std::wcout << L"CoInitializeEx failed: " << hr << std::endl; return 1; } IShellItem2* pItem = nullptr; hr = SHCreateItemFromParsingName(argv[1], nullptr, IID_PPV_ARGS(&pItem)); if (SUCCEEDED(hr)) { // 获取文件名 std::wcout << L"File Name: "; PrintPropertyValue(pItem, PKEY_ItemNameDisplay); // 获取创建日期 std::wcout << L"Created Date: "; PrintPropertyValue(pItem, PKEY_DateCreated); // 获取文件作者(如果是文档类文件) std::wcout << L"Author: "; PrintPropertyValue(pItem, PKEY_FileAuthor); // 获取文件描述(如果有) std::wcout << L"Description: "; PrintPropertyValue(pItem, PKEY_FileDescription); pItem->Release(); } else { std::wcout << L"Failed to create Shell item: " << hr << std::endl; } CoUninitialize(); return 0; }
枚举所有文件属性(详情标签里的全部内容)
如果你想一次性获取所有可用的属性及对应值,可以使用IPropertyStore接口来遍历:
void EnumerateAllProperties(IShellItem2* pItem) { IPropertyStore* pStore = nullptr; if (SUCCEEDED(pItem->GetPropertyStore(GPS_DEFAULT, IID_PPV_ARGS(&pStore)))) { DWORD count = 0; pStore->GetCount(&count); for (DWORD i = 0; i < count; i++) { PROPERTYKEY propKey; if (SUCCEEDED(pStore->GetAt(i, &propKey))) { // 获取属性名称 PWSTR pPropName = nullptr; PSGetNameFromPropertyKey(propKey, &pPropName); std::wcout << L"Property: " << pPropName << L" - "; // 获取属性值 PROPVARIANT propVar; PropVariantInit(&propVar); if (SUCCEEDED(pStore->GetValue(propKey, &propVar))) { // 这里可以复用之前的PrintPropertyValue逻辑处理值 switch (propVar.vt) { case VT_LPWSTR: std::wcout << propVar.pwszVal; break; case VT_FILETIME: { SYSTEMTIME st; FileTimeToSystemTime(&propVar.filetime, &st); std::wcout << st.wYear << L"/" << st.wMonth << L"/" << st.wDay; break; } default: std::wcout << L"[Unsupported Type]"; break; } PropVariantClear(&propVar); } std::wcout << std::endl; CoTaskMemFree(pPropName); } } pStore->Release(); } }
关键注意事项
- 需要链接
shell32.lib和propsys.lib(代码里用#pragma comment已经指定) - 必须初始化COM环境(
CoInitializeEx),使用完毕后要调用CoUninitialize - 不同类型的属性值需要对应不同的
PROPVARIANT类型处理,避免内存泄漏 - 部分属性只有特定类型的文件才有(比如
PKEY_FileAuthor只存在于文档、图片等带元数据的文件中)
内容的提问来源于stack exchange,提问作者Baron von Hoot
相关产品推荐
相关产品推荐

