我看到应该做this来比较PIDL:IShellFolder::CompareIDs()。

特别是,我试图检测给定的绝对PIDL(或相对)是否是控制面板的绝对PIDL。

但是,在实践中,我最后得到两个PIDL,它们的IShellFolder::CompareIDs()声明不相等,当它们应该相等时(查看每个的GetDisplayName(),我可以看到我们确实在查看控制面板) 。

基本上,我通过以下方式获取“控制面板”的绝对PIDL:

PIDL iidControlPanel = nullptr;
SHGetSpecialFolderLocation(hwnd, CSIDL_CONTROLS, &iidControlPanel);

然后像这样比较传入的枚举shell对象(请参见here以获取上下文-简而言之,这是在枚举CMFCShellTreeCtrl内部的桌面shell命名空间的结果):
bool bIsControlPanel = CompareAbsolutePIDLs(iidControlPanel, pItem->pidlFQ);

供引用,这是比较功能:
bool CompareAbsolutePIDLs(PIDLIST_ABSOLUTE pidl1, PIDLIST_ABSOLUTE pidl2)
{
    CComPtr<IShellFolder> ishDesk;
    SHGetDesktopFolder(&ishDesk);
    HRESULT hr = ishDesk->CompareIDs(SHCIDS_CANONICALONLY, pidl1, pidl2);
    return SUCCEEDED(hr) && HRESULT_CODE(hr) == 0;
}

在调试器中,我可以看到每个返回的GetDisplayName():
"::{26EE0668-A00A-44D7-9371-BEB064C98683}\0"
"::{26EE0668-A00A-44D7-9371-BEB064C98683}"

在这里,您可以看到PIDL的十六进制转储:
1f 70 68 06 ee 26 0a a0 d7 44 93 71 be b0 64 c9 86 83 *0c* 00
1f 70 68 06 ee 26 0a a0 d7 44 93 71 be b0 64 c9 86 83 *00* 00

除了倒数第二个值(00 vs. 0c)外,基础PIDLS也是二进制相同的。我现在不知道它们为什么与众不同,或者我能怎么解决这个问题?

问题
  • 是否有另一种方式来获取控件的PIDL,而该方式不包含看似虚假的额外null字节?
  • 或者,是否有更好的方法来获取枚举项的PIDL(CMFCShellTreeCtrol获得绝对PIDL的方式是否不够,以致于它无法包含最终的空字节?)
  • 是否可以获取控制面板作为相对PIDL,然后将其与相对枚举PIDL(我也有)进行比较?
  • ???
  • 最佳答案

    这些确实是不同的 shell 对象。您可以使用SIGDN_NORMALDISPLAY选项将获得的PIDL传递给SHGetNameFromIDList(),以将它们转换为可读的字符串。长的PIDL(带有0x0c)将转换为“所有控制面板项目”,短的PIDL将转换为“控制面板”。

    通过使用SHGetSpecialFolderLocation()检索控制面板控件的虚拟文件夹开始了此问题。与“控制面板”对象区别于桌面根目录。我认为您需要通过获取控制面板的PIDL来解决此问题,并忽略虚拟文件夹。一种方法是使用ILCloneFirst将虚拟文件夹转换为根对象:

     PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);
    

    或者,您可以对控制面板CLSID“:: {26EE0668-A00A-44D7-9371-BEB064C98683}”进行硬编码,然后使用SHParseDisplayName()将其转换为PIDL。

    09-04 15:55