我试图枚举给定路径上的所有文件并获取它们的属性。
在我下面的实现中,我不明白发生了什么,看起来它以某种方式使用计算机
desktop
路径而不是folderPath
上的路径
在
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &displayName);
显示:
C:\Users\Lilo\Desktop\file.txt
而不是:C:\Users\Lilo\Documents\file.txt
file.txt 位于文档文件夹中而不是桌面上
因此
SHGetPropertyStoreFromIDList
和 SHGetPropertyStoreFromParsingName
都失败了
HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) : The system cannot find the file specified.
#include <windows.h>
#include <iostream>
#include <shlobj.h>
#include <atlcomcli.h>
inline void enumFiles(const std::wstring& folderPath)
{
CoInitialize(NULL);
HRESULT hr;
CComPtr<IShellItem> pFolderItem = NULL;
CComPtr<IShellFolder> pFolder = NULL;
hr = SHCreateItemFromParsingName(folderPath.c_str(), NULL, IID_PPV_ARGS(&pFolderItem));
if (FAILED(hr))
{
std::cout << "SHCreateItemFromParsingName failed with HRESULT:" << hr;
CoUninitialize();
return;
}
hr = pFolderItem->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&pFolder));
if (FAILED(hr))
{
std::cout << "BindToHandler failed with HRESULT:" << hr;
CoUninitialize();
return;
}
CComPtr<IEnumIDList> pEnum = NULL;
hr = pFolder->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnum);
if (FAILED(hr))
{
std::cout << "EnumObjects failed with HRESULT:" << hr;
CoUninitialize();
return;
}
ITEMIDLIST* pidl = NULL;
ULONG fetched;
while (pEnum->Next(1, &pidl, &fetched) == S_OK)
{
CComPtr<IShellItem> pItem;
hr = SHCreateItemFromIDList(pidl, IID_PPV_ARGS(&pItem));
if (FAILED(hr))
{
std::cout << "SHCreateItemFromIDList failed with HRESULT:" << hr;
CoTaskMemFree(pidl);
continue;
}
LPWSTR displayName;
hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &displayName);
if (SUCCEEDED(hr))
CoTaskMemFree(displayName);
CComPtr<IPropertyStore> pPropertyStore;
GETPROPERTYSTOREFLAGS flags = GPS_DEFAULT;
hr = SHGetPropertyStoreFromIDList(pidl, flags, IID_PPV_ARGS(&pPropertyStore));
//hr = SHGetPropertyStoreFromParsingName(displayName, NULL, GPS_DEFAULT, IID_PPV_ARGS(&pPropertyStore));
CoTaskMemFree(pidl);
if (FAILED(hr))
{
std::cout << "SHGetPropertyStoreFromIDList failed with HRESULT:" << hr;
continue;
}
}
CoUninitialize();
}
int main(int argc, char* argv[])
{
enumFiles(L"C:\\Users\\Lilo\\Documents");
}
你可以继续使用
IShellItem
和朋友们(IEnumShellItems),IShellFolder
是底层文件夹界面,不太好用,像这样(省略错误检查):
void enumFiles(const std::wstring& folderPath)
{
CComPtr<IShellItem> folder;
SHCreateItemFromParsingName(folderPath.c_str(), nullptr, IID_PPV_ARGS(&folder));
CComPtr<IEnumShellItems> items;
folder->BindToHandler(nulptr, BHID_EnumItems, IID_PPV_ARGS(&items));
do
{
CComPtr<IShellItem> item;
if (items->Next(1, &item, nullptr) != S_OK)
break;
CComHeapPtr<wchar_t> displayName;
item->GetDisplayName(SIGDN_FILESYSPATH, &displayName);
std::wcout << displayName.m_pData << std::endl;
} while (true);
}
int main(int argc, char* argv[])
{
CoInitialize(NULL);
{
enumFiles(L"C:\\Users\\Lilo\\Documents");
}
CoUninitialize();
return 0;
}
PS 1:不要在库代码中调用
CoInitalize
,只需每个进程/线程调用一次即可。
PS 2:ATL 有
CComHeapPtr
用于智能内存指针。