How to enumerate files on a specific folder using Windows shell apis?
See the question and my original answer on StackOverflowYou can keep on using IShellItem
and friends (IEnumShellItems) all along, IShellFolder
is the underlying folder interface that's not easy to use, something like this (error-checks ommited):
void enumFiles(const std::wstring& folderPath)
{
CComPtr<IShellItem> folder;
SHCreateItemFromParsingName(folderPath.c_str(), nullptr, IID_PPV_ARGS(&folder));
// create a bind context to define what we want to enumerate
CComPtr<IPropertyBag> bag;
PSCreateMemoryPropertyStore(IID_PPV_ARGS(&bag));
CComPtr<IBindCtx> ctx;
CreateBindCtx(0, &ctx);
ctx->RegisterObjectParam((LPOLESTR)STR_PROPERTYBAG_PARAM, bag);
auto flags = CComVariant(SHCONTF_FOLDERS | SHCONTF_NONFOLDERS);
bag->Write(STR_ENUM_ITEMS_FLAGS, &flags);
CComPtr<IEnumShellItems> items;
folder->BindToHandler(ctx, 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;
CComPtr<IPropertyStore> store;
if (FAILED(item->BindToHandler(nullptr, BHID_PropertyStore, IID_PPV_ARGS(&store))))
{
CComPtr<IPropertyStoreFactory> factory;
item->BindToHandler(nullptr, BHID_PropertyStore, IID_PPV_ARGS(&factory));
factory->GetPropertyStore(GPS_BESTEFFORT, nullptr, IID_PPV_ARGS(&store));
}
// etc.
} while (true);
}
int main(int argc, char* argv[])
{
CoInitialize(NULL);
{
enumFiles(L"C:\\Users\\Lilo\\Documents");
}
CoUninitialize();
return 0;
}
See here for more on the possible bind contexts.
PS 1: don't call CoInitalize
in a library code, just call it once per process/thread.
PS 2: ATL has CComHeapPtr
for smart memory pointer.