为什么控制面板的PIDL会有所不同? [英] Why would the PIDL for the control panel be different?

查看:76
本文介绍了为什么控制面板的PIDL会有所不同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到应该这样做

I see that one should do this to compare PIDLs: IShellFolder::CompareIDs().

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

In particular, I'm trying to detect if a given absolute PIDL (or relative) is that of the Control Panel.

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

However, in practice I end up with two PIDLs which IShellFolder::CompareIDs() claims are not equal, when they should be (looking at the GetDisplayName() for each, I can see that we're indeed looking at the Control Panel).

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

Basically, I'm obtaining the absolute PIDL for the Control panel by:

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

然后像这样比较传入的枚举shell对象(请参阅

And then comparing the incoming enumerated shell object like so (see here for context - in a nutshell this is looking at the results of enumerating the desktop shell namespace inside of CMFCShellTreeCtrl):

bool bIsControlPanel = CompareAbsolutePIDLs(iidControlPanel, pItem->pidlFQ);

作为参考,下面是比较功能:

For reference, here's the comparison function:

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():

In the debugger, I can see that GetDisplayName() for each returns:

"::{26EE0668-A00A-44D7-9371-BEB064C98683}\0"
"::{26EE0668-A00A-44D7-9371-BEB064C98683}"

在这里您可以看到PIDL的十六进制转储:

Here you can see the hex dump of the PIDLs:

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也是二进制相同的.目前,我对它们为何与众不同感到困惑,或者我该怎么解决这个问题?!

The underlying PIDLS are also binary identical excepting the penultimate value (00 vs. 0c). I'm currently at a loss as to why they're different, or what I can do to resolve this issue?!

  1. 是否还有另一种方法来获取控件的PIDL,而该方法不包含看似虚假的额外null字节?
  2. 或者,是否有更好的方法来获取枚举项的PIDL(CMFCShellTreeCtrol获得绝对PIDL的方式是否不够,使得它不能包含最终的空字节?)
  3. 有没有办法获得控制面板作为相对PIDL,然后将其与相对枚举PIDL(我也有)进行比较?
  4. ???

推荐答案

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

These really are different shell objects. You can pass the PIDLs you got to SHGetNameFromIDList() with the SIGDN_NORMALDISPLAY option to convert them to readable strings. The long PIDL (with 0x0c) converts to "All Control Panel Items", the short one converts to "Control Panel".

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

This problem got started by using SHGetSpecialFolderLocation() to retrieve the virtual folder for the Control Panel controls. Distinct from the Control Panel object off the desktop root. I think you need to fix this by obtaining the PIDL for Control Panel and ignore the virtual folder. One way to do so is by using ILCloneFirst to convert the virtual folder to the root object:

 PITEMID_CHILD controlPanel = ILCloneFirst(iidControlPanel);

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

Or you can hard-code the control panel CLSID, "::{26EE0668-A00A-44D7-9371-BEB064C98683}", and convert it to a PIDL with SHParseDisplayName().

这篇关于为什么控制面板的PIDL会有所不同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆