如何正确枚举shell名称空间下的项目?

时间:2019-03-21 17:48:01

标签: windows mfc

背景:

  • 尝试port CMFCShellTreeCtrl
  • 多个GUID可能与同一外壳项目关联。例如,“下载”具有以下两个GUID:
    • :: {374DE290-123F-4565-9164-39C4925E467B}
    • :: {088E3905-0323-4B02-9826-5D99428E115F}

当我尝试使用以下代码枚举“此PC” /“我的电脑”下的外壳项目时,每个项目出现的次数与与其关联的GUID的次数一样多。例如,“下载”出现两次,而“ C:\”出现一次。

#include <iostream>
#include <ShlObj.h>

void test2() {
    SFGAOF sfgao;
    LPITEMIDLIST this_pc_pidl;
    SHParseDisplayName(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}"), NULL, &this_pc_pidl, SFGAO_FILESYSTEM, &sfgao);

    LPSHELLFOLDER this_pc_folder;
    SHBindToObject(NULL, this_pc_pidl, NULL, IID_IShellFolder, (LPVOID*)&this_pc_folder);

    const SHCONTF m_dwFlags = SHCONTF_FOLDERS;
    LPENUMIDLIST this_pc_enum;
    if (FAILED(this_pc_folder->EnumObjects(NULL, m_dwFlags, &this_pc_enum)) || this_pc_enum == NULL) {
        return;
    }

    LPITEMIDLIST sub_pidl_rel;
    DWORD dw_fetched;
    while ((SUCCEEDED(this_pc_enum->Next(1, &sub_pidl_rel, &dw_fetched)) && dw_fetched)) {
        STRRET ret;
        std::basic_string<TCHAR> s;

        if (S_OK == (this_pc_folder->GetDisplayNameOf(sub_pidl_rel, SHGDN_FORPARSING | SHGDN_INFOLDER, &ret)))
        {
            switch (ret.uType) {
            case STRRET_CSTR:
                s =  L"{CSTR}";
                break;
            case STRRET_OFFSET:
                s = L"{OFFSET}";
                break;
            case STRRET_WSTR:
                s = ret.pOleStr;
                break;
            default:
                s = L"{WTF}" + std::to_wstring(ret.uType);
                break;
            }
        }

        std::wcout << '<' << s << '>' << std::endl;
    }
}

通过使用CMFCShellTreeCtrl的源代码,在IShellFolder接口进行繁重的工作,我发现即使进行以下调整,即使是官方的MFC类也显示出令人讨厌的行为(同名出现两次):

  • 在另一个线程的枚举过程中(或之后或2秒后)枚举“此PC”,其父代又称为“桌面”。

但不是按其唯一设计的操作顺序进行操作:

  • 相关的UI事件到来后会枚举“此PC”。

总之,IShellFolder::EnumObjects在看似无关紧要的情况下为SAME shell文件夹提供了不同的结果。

那么CMFCShellTreeCtrl似乎是不确定的,无法正确运行,如何在与唯一可能的用户操作一致的单一情况下以某种方式正确运行?此外,在CLI而不是GUI下,如何在枚举CMFCShellTreeCtrl这样的shell名称空间下正确枚举项目?

谢谢。

0 个答案:

没有答案