[python-win32] Walking the shell namespace in Python

Mark Hammond skippy.hammond at gmail.com
Tue May 11 03:39:13 CEST 2010


On 7/05/2010 4:29 PM, Thomas Heller wrote:
> Tim Golden schrieb:
>> On 05/05/2010 20:33, Thomas Heller wrote:
>>> Does someone have example code snippets how to walk the shell namespace in Python?
>>> I'm lost in all these pidls and folders.
>>
>> The code below uses the pywin32 functions to walk. Because there's all
>> sorts of things which can happen, I've implemented a v. broad except:
>> clause just to keep things going. Since this uses the pywin32 wrappers,
>> it's hiding a certain amount of the PIDL/SHITEM stuff, but the functions
>> are pretty much the underlying win32 ones.
>>
>> One thing I don't know how to do without using comtypes is to find the parent.
>> the SHBindToParent function would be the way to go but it's not exposed and
>> I don't have the energy to set up all the comtypes boilerplate to make it happen:
>> I'm sure you can manage, though :)
>>
>>     http://msdn.microsoft.com/en-us/library/bb762114%28VS.85%29.aspx
>
> Thanks Tim, your script gave me a good start.
>
> It seems that pywin32 wraps pidls as list of strings, so getting the parent
> is as simple as removing the last part:
>
>>>> from win32com.shell.shell import *
>>>> from win32com.shell.shellcon import *
>>>> desktop = SHGetDesktopFolder()
>>>> desktop.ParseDisplayName(0, None, r"c:\python26\lib\site-packages")
> (0, ['\x1fP\xe0O\xd0 \xea:i\x10\xa2\xd8\x08\x00+00\x9d', '/C:\\\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
> 0\x00\x00', '1\x00\x00\x00\x00\x00\x9c<\xb82\x10\x00Python26\x00\x00(\x00\x03\x00\x04\x00\xef\xbe\x97:\x108\x9c<\xb82\x14\x00\x00\
> x00P\x00y\x00t\x00h\x00o\x00n\x002\x006\x00\x00\x00\x18\x00', '1\x00\x00\x00\x00\x00\x9d<\x02D\x10\x00Lib\x00\x1e\x00\x03\x00\x04\
> x00\xef\xbe\xfb:eQ\x9d<\x02D\x14\x00\x00\x00L\x00i\x00b\x00\x00\x00\x12\x00', '1\x00\x00\x00\x00\x00\x9c<\xafD\x10\x00SITE-P~1\x00
> \x002\x00\x03\x00\x04\x00\xef\xbe\xfb:uQ\x9c<\xafD\x14\x00\x00\x00s\x00i\x00t\x00e\x00-\x00p\x00a\x00c\x00k\x00a\x00g\x00e\x00s\x0
> 0\x00\x00\x18\x00'], 0)
>>>> eaten, pidl, attr = desktop.ParseDisplayName(0, None, r"c:\python26\lib\site-packages")
>>>> desktop.GetDisplayNameOf(pidl, SHGDN_FORPARSING)
> u'C:\\Python26\\Lib\\site-packages'
>>>> desktop.GetDisplayNameOf(pidl[:-1], SHGDN_FORPARSING)
> u'C:\\Python26\\Lib'
>>>> desktop.GetDisplayNameOf(pidl[:-2], SHGDN_FORPARSING)
> u'C:\\Python26'
>>>> desktop.GetDisplayNameOf(pidl[:-3], SHGDN_FORPARSING)
> u'C:\\'
>>>> desktop.GetDisplayNameOf(pidl[:-4], SHGDN_FORPARSING)
> u'::{20D04FE0-3AEA-1069-A2D8-08002B30309D}'
>>>>
>
> What I find strange if this:
>
>>>> desktop.GetDisplayNameOf(pidl, SHGDN_FORPARSING)
> u'C:\\Python26\\Lib\\site-packages'
>>>> desktop.GetDisplayNameOf(pidl, SHGDN_NORMAL)
> u'Python26'

IIRC, GetDisplayNameOf returns the name of a direct child - not the 
child of a child.  So the "correct" way to do this would be to find the 
direct parent of the PIDL you are interested in and ask that.

Also IIRC, the lack of SHBindToParent can be worked around with 
IShellFolder::BindToObject - SHBindToParent is just a helper around 
doing exactly that.

HTH,

Mark


More information about the python-win32 mailing list