我有一种情况,我想对一些Windows shell特殊文件夹(对应于CSIDL枚举中的值)执行特殊处理.(我的解决方案必须与WinXP兼容.)我遇到的问题是当我遇到IShellFolders时我沿着heirarchy工作,我找不到将IShellFolders与CSIDL相匹配的方法.
这是我目前的做法:
将所有CSIDL的静态一对一数据结构(csidlToFromFullPIdl)初始化为SHGetSpecialFolderLocation返回的pIDL.
foreach (CSIDL csidl in Enum.GetValues(typeof(CSIDL)) { IntPtr fullPIdl = IntPtr.Zero; int hResult = ShellApi.SHGetSpecialFolderLocation(IntPtr.Zero,csidl,ref fullPIdl); if (hResult != 0) Marshal.ThrowExceptionForHR(hResult); csidlToFromFullPIdl.Add(csidl,fullPIdl); }
使用Desktop IShellFolder启动heirarchy:
int hResult = ShellApi.SHGetDesktopFolder(ref _shellFolder); hResult = ShellApi.SHGetSpecialFolderLocation(IntPtr.Zero,CSIDL.CSIDL_DESKTOP,ref _fullPIdl);
像这样检索孩子:
hResult = _shellFolder.EnumObjects(IntPtr.Zero,SHCONTF.SHCONTF_FOLDERS,out pEnum); // Then repeatedly call: pEnum.Next(1,out childRelativePIdl,out numberGotten);
为孩子们构建新的完全合格的pIDL,如下所示:
_fullPIdl = ShellApi.ILCombine(parentFullPIdl,childRelativePIdl);
(最后,使用:)检索孩子的IShellFolder
hResultUint = parentShellItem.ShellFolder.BindToObject(childRelativePIdl,IntPtr.Zero,ShellApi.IID_IShellFolder,out _shellFolder);
我遇到的问题是childRelativePIdl和_fullPIdl都不对应csidlToFromFullPIdl中的任何pIDL.
TIA.
在Vista机器上的FYI GUID corresponding to KNOWNFOLDERIDs可能是一个解决方案(但不适合我,因为我必须兼容WinXP.)
我还应该说我认为使用特殊文件夹的路径(通过SHGetSpecialFolderPath)是不够的,因为我感兴趣的几个特殊文件夹没有路径. (例如,CSIDL_DRIVES和CSIDL_NETWORK.)
我正在尝试两种方法.第一种是使用SHGetDataFromIDList来检索Clsid,然后我可以将其与已知的Clsids进行比较:
public static Guid GetClsidFromFullPIdl(IntPtr fullPIdl) { // Get both parent's IShellFolder and pIDL relative to parent from full pIDL IntPtr pParentShellFolder; IntPtr relativePIdl = IntPtr.Zero; int hResultInt = ShellApi.SHBindToParent(fullPIdl,ShellGuids.IID_IShellFolder,out pParentShellFolder,ref relativePIdl); if (hResultInt != (int)HRESULT.S_OK) Marshal.ThrowExceptionForHR(hResultInt); object parentShellFolderObj = System.Runtime.InteropServices.Marshal.GetTypedObjectForIUnknown( pParentShellFolder,typeof(IShellFolder)); IShellFolder parentShellFolder = (IShellFolder)parentShellFolderObj; SHDESCRIPTIONID descriptionId = new SHDESCRIPTIONID(); IntPtr pDescriptionId = MarshalToPointer(descriptionId); // Next line returns hResult corresponding to NotImplementedException hResultInt = ShellApi.SHGetDataFromIDList(parentShellFolder,ref relativePIdl,SHGDFIL.SHGDFIL_DESCRIPTIONID,pDescriptionId,Marshal.SizeOf(typeof(SHDESCRIPTIONID))); if (hResultInt != (int)HRESULT.S_OK) Marshal.ThrowExceptionForHR(hResultInt); if (parentShellFolder != null) Marshal.ReleaseComObject(parentShellFolder); return descriptionId.Clsid; } static IntPtr MarshalToPointer(object data) { IntPtr pData = Marshal.AllocHGlobal(Marshal.SizeOf(data)); Marshal.StructureToPtr(data,pData,false); return pData; }
这种方法的问题是对SHGetDataFromIDList的调用返回一个对应于抛出NotImplementedException的hResult.这是否意味着SHGetDataFromIDList在我的系统上不可用? (WinXP SP3.)
我的第二种方法是将两个指针引用的项目标识符列表与项目标识符列表进行比较,看它们是否相等.我正在用C编写here编码的技术.这是我到目前为止所做的:
每
Raymond Chen:ITEMIDLIST可以是等效的,而不是逐字节相同的.使用
IShellFolder::CompareIDs测试等效性.