C#:如何使用 SHOpenFolderAndSelectItems [重复]

2024-05-22

有人可以举例说明如何使用 shell 函数吗SH打开文件夹并选择项目 http://msdn.microsoft.com/en-us/library/bb762232(VS.85).aspx来自 C#?我不太明白如何使用这些功能,也找不到它pinvoke.net http://www.pinvoke.net/... =/

假设我有三个文件

  • X:\Pictures\a.jpg
  • X:\Pictures\s.jpg
  • X:\Pictures\d.jpg

然后我想打开X:\Pictures文件夹与a.jpg, s.jpg and d.jpg已选择。


正如您似乎已经问了两次相同的问题(另一个是C#:如何打开 Windows 资源管理器窗口并选择多个文件 https://stackoverflow.com/questions/1073353/c-how-to-open-windows-explorer-windows-with-a-number-of-files-selected没有答案)我发布了我对这两个问题的解决方案,我不知道是否应该将其中一个作为社区维基。

在同事遇到问题后寻找答案时,我没有找到答案,所以我写了一个小课程来做到这一点。代码是在要点上 http://gist.github.com/551626我将在本文末尾粘贴当前版本。

对于您的示例文件,语法将是:

 ShowSelectedInExplorer.FilesOrFolders(
  @"X:\Pictures\a.jpg",
  @"X:\Pictures\s.jpg",
  @"X:\Pictures\d.jpg"
  );

与低级 API 相比,我的代码有一些限制,主要是:

  • 未实现桌面选择
  • 父目录必须是目录或驱动器,因此您不能在“我的电脑”文件夹中选择多个驱动器。

无论如何,这是 ShowSelectedInExplorer 类源代码:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;

static class ShowSelectedInExplorer
{
    [Flags]
    internal enum SHCONT : ushort
    {
        SHCONTF_CHECKING_FOR_CHILDREN = 0x0010,
        SHCONTF_FOLDERS = 0x0020,
        SHCONTF_NONFOLDERS = 0x0040,
        SHCONTF_INCLUDEHIDDEN = 0x0080,
        SHCONTF_INIT_ON_FIRST_NEXT = 0x0100,
        SHCONTF_NETPRINTERSRCH = 0x0200,
        SHCONTF_SHAREABLE = 0x0400,
        SHCONTF_STORAGE = 0x0800,
        SHCONTF_NAVIGATION_ENUM = 0x1000,
        SHCONTF_FASTITEMS = 0x2000,
        SHCONTF_FLATLIST = 0x4000,
        SHCONTF_ENABLE_ASYNC = 0x8000
    }

    [ComImport,
    Guid("000214E6-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
    ComConversionLoss]
    internal interface IShellFolder
    {
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void ParseDisplayName(IntPtr hwnd, [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc, [In, MarshalAs(UnmanagedType.LPWStr)] string pszDisplayName, [Out] out uint pchEaten, [Out] out IntPtr ppidl, [In, Out] ref uint pdwAttributes);
        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int EnumObjects([In] IntPtr hwnd, [In] SHCONT grfFlags, [MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenumIDList);

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int BindToObject([In] IntPtr pidl, [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc, [In] ref Guid riid, [Out, MarshalAs(UnmanagedType.Interface)] out IShellFolder ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void BindToStorage([In] ref IntPtr pidl, [In, MarshalAs(UnmanagedType.Interface)] IBindCtx pbc, [In] ref Guid riid, out IntPtr ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void CompareIDs([In] IntPtr lParam, [In] ref IntPtr pidl1, [In] ref IntPtr pidl2);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void CreateViewObject([In] IntPtr hwndOwner, [In] ref Guid riid, out IntPtr ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void GetAttributesOf([In] uint cidl, [In] IntPtr apidl, [In, Out] ref uint rgfInOut);


        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void GetUIObjectOf([In] IntPtr hwndOwner, [In] uint cidl, [In] IntPtr apidl, [In] ref Guid riid, [In, Out] ref uint rgfReserved, out IntPtr ppv);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void GetDisplayNameOf([In] ref IntPtr pidl, [In] uint uFlags, out IntPtr pName);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        void SetNameOf([In] IntPtr hwnd, [In] ref IntPtr pidl, [In, MarshalAs(UnmanagedType.LPWStr)] string pszName, [In] uint uFlags, [Out] IntPtr ppidlOut);
    }

    [ComImport,
    Guid("000214F2-0000-0000-C000-000000000046"),
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    internal interface IEnumIDList
    {
        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Next(uint celt, IntPtr rgelt, out uint pceltFetched);

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Skip([In] uint celt);

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Reset();

        [PreserveSig]
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        int Clone([MarshalAs(UnmanagedType.Interface)] out IEnumIDList ppenum);
    }

    class NativeMethods
    {
        static readonly int pointerSize = Marshal.SizeOf(typeof(IntPtr));

        [DllImport("ole32.dll", EntryPoint = "CreateBindCtx")]
        public static extern int CreateBindCtx_(int reserved, out IBindCtx ppbc);

        public static IBindCtx CreateBindCtx()
        {
            IBindCtx result;
            Marshal.ThrowExceptionForHR(CreateBindCtx_(0, out result));
            return result;
        }

        [DllImport("shell32.dll", EntryPoint = "SHGetDesktopFolder", CharSet = CharSet.Unicode, SetLastError = true)]
        static extern int SHGetDesktopFolder_([MarshalAs(UnmanagedType.Interface)] out IShellFolder ppshf);

        public static IShellFolder SHGetDesktopFolder()
        {
            IShellFolder result;
            Marshal.ThrowExceptionForHR(SHGetDesktopFolder_(out result));
            return result;
        }

        [DllImport("shell32.dll", EntryPoint = "SHOpenFolderAndSelectItems")]
        static extern int SHOpenFolderAndSelectItems_(
            [In] IntPtr pidlFolder, uint cidl, [In, Optional, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl, int dwFlags
            );

        public static void SHOpenFolderAndSelectItems(IntPtr pidlFolder, IntPtr[] apidl, int dwFlags)
        {
            var cidl = (apidl != null) ? (uint)apidl.Length : 0U;
            var result = NativeMethods.SHOpenFolderAndSelectItems_(pidlFolder, cidl, apidl, dwFlags);
            Marshal.ThrowExceptionForHR(result);
        }

        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        public static extern IntPtr ILCreateFromPath([In, MarshalAs(UnmanagedType.LPWStr)] string pszPath);

        [DllImport("shell32.dll")]
        public static extern void ILFree([In] IntPtr pidl);
    }

    static IntPtr GetShellFolderChildrenRelativePIDL(IShellFolder parentFolder, string displayName)
    {
        var bindCtx = NativeMethods.CreateBindCtx();

        uint pchEaten;
        uint pdwAttributes = 0;
        IntPtr ppidl;
        parentFolder.ParseDisplayName(IntPtr.Zero, null, displayName, out pchEaten, out ppidl, ref pdwAttributes);

        return ppidl;
    }

    static IntPtr PathToAbsolutePIDL(string path)
    {
        var desktopFolder = NativeMethods.SHGetDesktopFolder();
        return GetShellFolderChildrenRelativePIDL(desktopFolder, path);
    }

    static Guid IID_IShellFolder = typeof(IShellFolder).GUID;
    static int pointerSize = Marshal.SizeOf(typeof(IntPtr));

    static IShellFolder PIDLToShellFolder(IShellFolder parent, IntPtr pidl)
    {
        IShellFolder folder;
        var result = parent.BindToObject(pidl, null, ref IID_IShellFolder, out folder);
        Marshal.ThrowExceptionForHR((int)result);
        return folder;
    }

    static IShellFolder PIDLToShellFolder(IntPtr pidl)
    {
        return PIDLToShellFolder(NativeMethods.SHGetDesktopFolder(), pidl);
    }

    static void SHOpenFolderAndSelectItems(IntPtr pidlFolder, IntPtr[] apidl, bool edit)
    {
        NativeMethods.SHOpenFolderAndSelectItems(pidlFolder, apidl, edit ? 1 : 0);
    }

    public static void FileOrFolder(string path, bool edit = false)
    {
        if (path == null) throw new ArgumentNullException("path");

        var pidl = PathToAbsolutePIDL(path);
        try
        {
            SHOpenFolderAndSelectItems(pidl, null, edit);
        }
        finally
        {
            NativeMethods.ILFree(pidl);
        }
    }

    static IEnumerable<FileSystemInfo> PathToFileSystemInfo(IEnumerable<string> paths)
    {
        foreach (var path in paths)
        {
            string fixedPath = path;
            if (fixedPath.EndsWith(Path.DirectorySeparatorChar.ToString()) || fixedPath.EndsWith(Path.AltDirectorySeparatorChar.ToString()))
            {
                fixedPath = fixedPath.Remove(fixedPath.Length - 1);
            }

            if (Directory.Exists(fixedPath)) yield return new DirectoryInfo(fixedPath);
            else if (File.Exists(fixedPath)) yield return new FileInfo(fixedPath);
            else
            {
                throw new FileNotFoundException("The specified file or folder doesn't exists : " + fixedPath, fixedPath);
            }
        }
    }

    public static void FilesOrFolders(string parentDirectory, ICollection<string> filenames)
    {
        if (filenames == null) throw new ArgumentNullException("filenames");
        if (filenames.Count == 0) return;

        var parentPidl = PathToAbsolutePIDL(parentDirectory);
        try
        {
            var parent = PIDLToShellFolder(parentPidl);

            List<IntPtr> filesPidl = new List<IntPtr>(filenames.Count);
            foreach (var filename in filenames)
            {
                filesPidl.Add(GetShellFolderChildrenRelativePIDL(parent, filename));
            }

            try
            {
                SHOpenFolderAndSelectItems(parentPidl, filesPidl.ToArray(), false);
            }
            finally
            {
                foreach (var pidl in filesPidl)
                {
                    NativeMethods.ILFree(pidl);
                }
            }
        }
        finally
        {
            NativeMethods.ILFree(parentPidl);
        }
    }

    public static void FilesOrFolders(params string[] paths)
    {
        FilesOrFolders((IEnumerable<string>)paths);
    }

    public static void FilesOrFolders(IEnumerable<string> paths)
    {
        FilesOrFolders(PathToFileSystemInfo(paths));
    }

    public static void FilesOrFolders(IEnumerable<FileSystemInfo> paths)
    {
        if (paths == null) throw new ArgumentNullException("paths");
        if (paths.Count() == 0) return;

        var explorerWindows = paths.GroupBy(p => Path.GetDirectoryName(p.FullName));

        foreach (var explorerWindowPaths in explorerWindows)
        {
            var parentDirectory = Path.GetDirectoryName(explorerWindowPaths.First().FullName);
            FilesOrFolders(parentDirectory, explorerWindowPaths.Select(fsi => fsi.Name).ToList());
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#:如何使用 SHOpenFolderAndSelectItems [重复] 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 调用 McAfee 病毒扫描引擎

    我收到客户的请求 要求使用他们服务器上的 McAfee 病毒扫描将病毒扫描集成到应用程序中 我做了一些调查 发现 McScan32 dll 是主要的扫描引擎 它导出各种看起来有用的函数 我还发现提到了 McAfee Scan Engine
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 如何连接重叠的圆圈?

    我想在视觉上连接两个重叠的圆圈 以便 becomes 我已经有部分圆的方法 但现在我需要知道每个圆的重叠角度有多大 但我不知道该怎么做 有人有主意吗 Phi ArcTan Sqrt 4 R 2 d 2 d HTH Edit 对于两个不同的半
  • C++ 多行字符串原始文字[重复]

    这个问题在这里已经有答案了 我们可以像这样定义一个多行字符串 const char text1 part 1 part 2 part 3 part 4 const char text2 part 1 part 2 part 3 part 4
  • 访问外部窗口句柄

    我当前正在处理的程序有问题 这是由于 vista Windows 7 中增强的安全性引起的 特别是 UIPI 它阻止完整性级别较低的窗口与较高完整性级别的窗口 对话 就我而言 我想告诉具有高完整性级别的窗口进入我们的应用程序 它在 XP 或
  • WPF 数据绑定到复合类模式?

    我是第一次尝试 WPF 并且正在努力解决如何将控件绑定到使用其他对象的组合构建的类 例如 如果我有一个由两个单独的类组成的类 Comp 为了清楚起见 请注意省略的各种元素 class One int first int second cla
  • 以编程方式在java的resources/source文件夹中创建文件?

    我有两个资源文件夹 src 这是我的 java 文件 资源 这是我的资源文件 图像 properties 组织在文件夹 包 中 有没有办法以编程方式在该资源文件夹中添加另一个 properties 文件 我尝试过这样的事情 public s
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 如何在 Android 中使用 C# 生成的 RSA 公钥?

    我想在无法假定 HTTPS 可用的情况下确保 Android 应用程序和 C ASP NET 服务器之间的消息隐私 我想使用 RSA 来加密 Android 设备首次联系服务器时传输的对称密钥 RSA密钥对已在服务器上生成 私钥保存在服务器
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • C# 中最小化字符串长度

    我想减少字符串的长度 喜欢 这串 string foo Lorem ipsum dolor sit amet consectetur adipiscing elit Aenean in vehicula nulla Phasellus li
  • 在OpenGL中,我可以在坐标(5, 5)处精确地绘制一个像素吗?

    我所说的 5 5 正是指第五行第五列 我发现使用屏幕坐标来绘制东西非常困难 OpenGL 中的所有坐标都是相对的 通常范围从 1 0 到 1 0 为什么阻止程序员使用屏幕坐标 窗口坐标如此严重 最简单的方法可能是通过以下方式设置投影以匹配渲
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template

随机推荐

  • Flutter - 如何将用户数据传递到所有视图

    我是 Flutter 世界和移动应用程序开发的新手 并且正在努力解决如何在整个应用程序中传递用户数据的问题 我已经尝试了几件事 但似乎没有一个很好 我确信我应该遵循一些最佳实践模式 因为它使示例更容易 所以我使用 firebase 进行身份
  • 如何防止 CSS 或 jQuery 中单词和标点符号之间的换行

    我在一个段落中有一些文字 我的问题是 当标点符号位于单词末尾时 有时可以换行到下一行 像这样 This is the text This is a new line 我可以用 CSS 或 jQuery 解决这个问题吗 如果您不在单词和标点符
  • 在运行时更改 swagger-ui 服务器变量

    使用 openapi v3 配置 我有一个名为 主机名 的服务器变量 用于构建 url 例如 servers url http hostname api variables hostname default some default her
  • 保留以下文本的标题

    我正在使用 css 列计数功能将我的部分分成两列 在一个页面上 我在第一列的底部有一个 h3 标题 在下一列的顶部有一个 p 段落 我想保留该段落的前几句话的标题 我可以将其与整个段落一起包装在使用 inline block 样式的 div
  • 如何使用 YouTube Data API v3 获取直播小 URL

    function authenticate return gapi auth2 getAuthInstance signIn scope https www googleapis com auth youtube readonly then
  • 多维数组将每个列表数组存储在另一个数组中

    我嵌套了可能有 2 或 3 层深度的多维数组 在它里面我可能有也可能没有列表数组 我需要循环数组 Array 0 gt Array id gt 1 name gt cat name 1 list gt Array 1 gt swgdgbdg
  • JPA中如何连接多个数据库?

    我有一个 Spring Boot 应用程序 当前使用 JPA 连接到单个数据库 application properties 文件中的连接详细信息 spring datasource url jdbc oracle thin localho
  • PHP 中是否有像 C++ 一样的纯虚函数

    我本以为很多人会想知道这是否可能 但我找不到任何重复的问题 请纠正我 我只是想知道PHP是否提供纯虚函数 我想要以下 class Parent no implementation given public function foo noth
  • 如何重定向到 warp 中带有尾部斜杠的 URL?

    我在用warp https crates io crates warp提供静态文件目录 不幸的是 当我在路径中添加尾部斜杠时 只能解析这些静态文件中使用的相对链接 这是我用来服务目录的代码 let route warp path segme
  • 为什么以下代码不允许我使用 fgets 获取用户输入但可以使用 scanf?

    这是一个更大程序的简短摘录 但该程序的其余部分无关紧要 因为我认为我能够隔离该问题 我怀疑这与我使用 fgets 的方式有关 我读过 最好使用 fgets 而不是 scanf 但我似乎无法让它在这里正常工作 当我使用以下代码时 程序不会给我
  • javascript捕获文本区域中的粘贴事件

    我目前有一个文本区域 我需要控制已粘贴的文本 本质上 我需要能够将用户想要粘贴到文本区域中的任何内容并将其放入变量中 然后我将计算出他们粘贴文本的位置和字符串的大小 以将其从文本区域中删除 然后最后用我自己的方式处理变量中的文本 我的问题
  • 是否可以在android中打印网页而不弹出窗口?

    我正在使用默认的 Android 打印机选项 Android 版本 4 4 我想绕过 printManager 适配器弹出窗口 如何在android中隐藏弹出窗口并直接打印到打印机 您不能扩展 PrintManager 类 这是最后一堂课
  • 各种中断的区别:SCI、SMI、NMI、普通中断

    我正在学习英特尔架构 到目前为止我遇到过几种类型的中断 SCI 系统控制中断 硬件使用的系统中断 用于向操作系统通知 ACPI 事件 SCI 是一个有效 低电平 可共享的电平中断 SMI 系统管理中断 由遗留系统上的中断事件生成的操作系统透
  • Android Studio:src/androidTest 和 src/main 文件夹之间的区别?

    我是 Android Studio 的新手 我的问题是 src androidTest 和 src main 文件夹有什么区别 我所有的课程应该放在哪里 Refer Android Studio 概述 http developer andr
  • 氡变换线检测

    我正在尝试检测灰度图像中的线条 为此 我在 MATLAB 中使用 Radon 变换 我的 m 文件的示例如下所示 我可以使用此代码检测多行 我还使用线条的移位和旋转属性来绘制线条 但是 我不明白在获取rho和theta值后如何获取检测线的起
  • CAKeyFrameAnimation 中的 keyTime 是什么样的值?

    例如我有这个 CAKeyFrameAnimation CALayer theLayer myView layer CAKeyframeAnimation animation animation CAKeyframeAnimation ani
  • 抽象类和接口之间的区别[重复]

    这个问题在这里已经有答案了 可能的重复 接口与基类 https stackoverflow com questions 56867 interface vs base class 我不明白抽象类和接口之间的区别 我什么时候需要使用哪种字体
  • 使用 r 以周为单位对数据进行分组

    I have a CVS file which has data for different countries at different weeks of this year I want to create a summary data
  • 在 Ruby 中,围绕子方法执行块的最佳方法是什么?

    我有一个父类 class Base def my method block method do EXECUTE WHATEVER S IN THE CHILD VERSION OF my method HOW TO DO end end d
  • C#:如何使用 SHOpenFolderAndSelectItems [重复]

    这个问题在这里已经有答案了 有人可以举例说明如何使用 shell 函数吗SH打开文件夹并选择项目 http msdn microsoft com en us library bb762232 VS 85 aspx来自 C 我不太明白如何使用