【问题标题】:Wildcards and IShellFolder enumeration?通配符和 IShellFolder 枚举?
【发布时间】:2019-10-25 09:49:48
【问题描述】:

我想尝试离开FindFirstFile()/FindNextFile() 并直接使用IShellFolder 来获取文件列表。原因是我想通过SHNCreateItemFromIDList() 为每个文件获取一个IShellItem,并且我将拥有传递给函数所需的一切。如果我使用文件路径函数,我想我每次都需要在传递给SHCreateItemFromParsingName() 之前构建完整路径,但我会问另一个特定的问题。

我的问题仅限于使用IShellFolder 使用通配符枚举文件和文件夹。有没有内置的东西可以做到这一点,还是你必须自己做文件匹配?

TIA!!

【问题讨论】:

  • IShellFolder 枚举不支持通配符。您必须手动过滤子项

标签: shell winapi com


【解决方案1】:

您不能使用 IShellFolder 进行过滤,但您可以使用 Shell 中内置的搜索工具以编程方式执行相同的操作,就像使用 Windows 资源管理器 UI 一样。

例如,您可以在右上角的搜索框中键入 ext:.txt 之类的内容,这意味着您要过滤所有带有 .txt的文件> 扩展:

这是一些等效的 C++ 示例代码(我已经删除了每一行的错误检查,但请确保您测试了所有可能的错误):

int main()
{
  CoInitialize(NULL);
  {
    CComPtr<ISearchFolderItemFactory> search;
    CComPtr<IShellItem> item;
    CComPtr<IShellItemArray> items;
    CComPtr<IQueryParserManager> mgr;
    CComPtr<IQueryParser> parser;
    CComPtr<IQuerySolution> solution;
    CComPtr<ICondition> condition;
    CComPtr<IShellItem> searchItem;
    CComPtr<IEnumShellItems> enumItems;

    // create search folder factory
    search.CoCreateInstance(CLSID_SearchFolderItemFactory);

    // create d:\temp shell item and set search folder scope to it
    SHCreateItemFromParsingName(L"d:\\temp", NULL, IID_PPV_ARGS(&item));
    SHCreateShellItemArrayFromShellItem(item, IID_PPV_ARGS(&items));
    search->SetScope(items);

    // create the query parser manager
    mgr.CoCreateInstance(CLSID_QueryParserManager);
    mgr->CreateLoadedParser(L"", 0, IID_PPV_ARGS(&parser));

    // parse an ms-search expression
    parser->Parse(L"ext:.txt", NULL, &solution);

    // get the condition the parser has built for us
    solution->GetQuery(&condition, NULL);

    // give the condition to the search folder factory
    search->SetCondition(condition);

    // get the search result back as a shell item (a virtual folder) and enumerates it
    search->GetShellItem(IID_PPV_ARGS(&searchItem));
    searchItem->BindToHandler(NULL, BHID_EnumItems, IID_PPV_ARGS(&enumItems));

    do
    {
      CComPtr<IShellItem> child;
      ULONG fetched;
      HRESULT hr2 = enumItems->Next(1, &child, &fetched);
      if (!fetched)
        break;

      // get the display name (for example)
      CComHeapPtr<WCHAR> name;
      child->GetDisplayName(SIGDN_NORMALDISPLAY, &name);
      wprintf(L"item: %s\n", name);

      CComHeapPtr<WCHAR> path;
      child->GetDisplayName(SIGDN_FILESYSPATH, &path);
      wprintf(L" path: %s\n", path);
    } while (TRUE);
  }
  CoUninitialize();
  return 0;
}

search-ms 语言非常强大。它的语法在这里可用:Querying the Index with the search-ms Protocol

【讨论】:

  • 谢谢,我在其他一些示例中看到了一些关于 ISearchFolderItemFactory 的内容。但是很高兴在这里记录了如何做到这一点。虽然,它看起来确实有很多步骤/工作,但没有一个易于使用的类。
【解决方案2】:

shell API 提供枚举,但没有任何类似于FindFirstFile()/FindNextFile() 的过滤或通配符功能。

因此,在使用 shell 枚举功能时,您必须手动过滤项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-10
    相关资源
    最近更新 更多