如何用C#获取shell:Desktop这类Shell文件夹的文件和文件夹列表?
问题原因
Environment.SpecialFolder.DesktopDirectory指向的是用户本地桌面的物理文件系统目录,仅包含实际存储在该路径下的文件和文件夹。shell:Desktop是Windows Shell提供的虚拟命名空间视图,除了本地桌面内容,还整合了系统级Shell对象(如驱动器、This PC、库),这些对象不属于传统文件系统路径,无法通过DirectoryInfo这类文件系统API访问。
解决方案
要获取shell:Desktop中的所有内容,需要调用Windows Shell API,以下是两种可行实现方式:
方式1:使用Windows API Code Pack
这是最简便的方式,该库封装了Shell相关的.NET接口,无需手动处理原生API:
using Microsoft.WindowsAPICodePack.Shell; // 获取Shell桌面命名空间实例 ShellObject desktop = ShellObject.FromParsingName("shell:Desktop"); // 遍历所有子项 foreach (ShellObject item in desktop) { Console.WriteLine(item.Name); // 若为文件系统项,可获取其实际路径 if (item is ShellFile file) Console.WriteLine($"路径: {file.Path}"); }
需通过NuGet安装
WindowsAPICodePack-Shell包。
方式2:手动调用Shell32.dll(无第三方依赖)
如果不想引入外部库,可以直接P/Invoke原生Shell API实现:
using System; using System.Collections.Generic; using System.Runtime.InteropServices; public class ShellDesktopHelper { [ComImport] [Guid("13709620-C279-11CE-A49E-444553540000")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IShellFolder { void ParseDisplayName(IntPtr hwnd, IntPtr pbc, [MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, out uint pchEaten, out IntPtr ppidl, ref uint pdwAttributes); void EnumObjects(IntPtr hwnd, uint grfFlags, out IEnumIDList ppenumIDList); } [ComImport] [Guid("000214F2-0000-0000-C000-000000000046")] private class ShellDesktopFolder { } [ComImport] [Guid("000214F3-0000-0000-C000-000000000046")] [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] private interface IEnumIDList { void Next(uint celt, IntPtr rgelt, out uint pceltFetched); void Reset(); } [DllImport("shell32.dll", CharSet = CharSet.Unicode)] private static extern int SHGetNameFromIDList(IntPtr pidl, uint uFlags, [Out] char[] pszName); private const uint SHCONTF_FOLDERS = 0x0001; private const uint SHCONTF_NONFOLDERS = 0x0002; private const uint SHGNF_NORMAL = 0x0000; public static List<string> GetShellDesktopItems() { var items = new List<string>(); var desktopFolder = new ShellDesktopFolder() as IShellFolder; if (desktopFolder == null) return items; desktopFolder.EnumObjects(IntPtr.Zero, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, out var enumIDList); enumIDList.Reset(); IntPtr pidl = IntPtr.Zero; uint fetched; while (true) { enumIDList.Next(1, pidl, out fetched); if (fetched != 1) break; var nameBuffer = new char[260]; if (SHGetNameFromIDList(pidl, SHGNF_NORMAL, nameBuffer) == 0) { var name = new string(nameBuffer).TrimEnd('\0'); items.Add(name); } Marshal.FreeCoTaskMem(pidl); } return items; } // 使用示例 public static void Main() { foreach (var item in GetShellDesktopItems()) { Console.WriteLine(item); } } }
内容的提问来源于stack exchange,提问作者Indy Singh
相关产品推荐
相关产品推荐

