热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#打开目录并选中文件(夹)的实现

很久之前想把这个写下来的,谁知道用Firefox在博客园上在线编辑快完成时浏览器死掉,郁闷之下没有写了。今天突然想起,随便记录一下吧。本文

  很久之前想把这个写下来的,谁知道用Firefox在博客园上在线编辑快完成时浏览器死掉,郁闷之下没有写了。今天突然想起,随便记录一下吧。

 

  本文想讲的内容,如果你还不是很清楚,可以看看下图:

 


 

  没错,就是想实现像上图中点击“查找目标”按钮一样的功能,即是打开目录并选中文件(夹)。有人可能会问,使用explorer.exe程序加/select参数不是可以做到吗?当然,这是一种办法,不过,也许你更希望使用Windows中的某个API来实现,因为使用explorer.exe程序来实现会有些问题的。那么,Windows中哪个API可以做到呢?答案是shell32.dll中的SHOpenFolderAndSelectItems函数,关于它的详细信息可以查看MSDN,需要注意的是这个API要在Windows XP及以上操作系统才支持。

 

  如果你希望使用VC来实现,那么网上也有很多例子,并且支持Windows XP以下的操作系统,可是我在网上找不到C#实现的例子,或许有我没有找到,所以只好自己动手,丰衣足食了。

 

  首先,C#导入shell32.dll中的SHOpenFolderAndSelectItems函数:

 

        [DllImport("shell32.dll", ExactSpelling = true)]

        public static extern int SHOpenFolderAndSelectItems(

            IntPtr pidlFolder,

            uint cidl,

            [In, MarshalAs(UnmanagedType.LPArray)] IntPtr[] apidl,

            uint dwFlags);

 

  VC中的一些数据类型,我们使用.NET中的IntPtr特定类型来代替行了,因为我们并不关心这些数据类型的数据,知道指针就OK了。SHOpenFolderAndSelectItems的第一个参数pidlFolder指你要查找的目标文件(夹)的PIDL,我们为了获取文件(夹)的PIDL,需要使用shell32.dll中的IShellLink接口。那么我们需要创建IShellLink接口的一个实例,需要使用到ole32.dll中的CoCreateInstance函数。创建的实例保存到指针,如下:

 

        [DllImport("ole32.dll", ExactSpelling = true)]

        public static extern int CoCreateInstance(

            [In] ref Guid rclsid,

            IntPtr pUnkOuter,

            CLSCTX dwClsContext,

            [In] ref Guid riid,

            [Out] out IntPtr ppv);

 

        public enum CLSCTX : uint

        {

            INPROC_SERVER = 0x1

        }

 

        Guid CLSID_ShellLink = new Guid("00021401-0000-0000-C000-000000000046");

        Guid IID_IShellLink = new Guid("000214F9-0000-0000-C000-000000000046");

 

        IntPtr ppsl = IntPtr.Zero;

        int result = CoCreateInstance(

            ref CLSID_ShellLink,

            IntPtr.Zero,

            CLSCTX.INPROC_SERVER,

            ref IID_IShellLink,

            out ppsl);

 

  这样,ppsl变量就保存了IShellLink的一个实例对象,为了使用IShellLink接口中的方法,我们还需要定义IShellLink接口,下面是Unicode版本的IShellLink,名为IShellLinkW:

 

    [ComImport]

    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

    [Guid("000214F9-0000-0000-C000-000000000046")]

    public interface IShellLinkW

    {

        [PreserveSig]

        int GetPath(StringBuilder pszFile, int cch, [In, Out] ref WIN32_FIND_DATAW pfd, uint fFlags);

 

        [PreserveSig]

        int GetIDList([Out] out IntPtr ppidl);

 

        [PreserveSig]

        int SetIDList([In] ref IntPtr pidl);

 

        [PreserveSig]

        int GetDescription(StringBuilder pszName, int cch);

 

        [PreserveSig]

        int SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);

 

        [PreserveSig]

        int GetWorkingDirectory(StringBuilder pszDir, int cch);

 

        [PreserveSig]

        int SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);

 

        [PreserveSig]

        int GetArguments(StringBuilder pszArgs, int cch);

 

        [PreserveSig]

        int SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);

 

        [PreserveSig]

        int GetHotkey([Out] out ushort pwHotkey);

 

        [PreserveSig]

        int SetHotkey(ushort wHotkey);

 

        [PreserveSig]

        int GetShowCmd([Out] out int piShowCmd);

 

        [PreserveSig]

        int SetShowCmd(int iShowCmd);

 

        [PreserveSig]

        int GetIconLocation(StringBuilder pszIconPath, int cch, [Out] out int piIcon);

 

        [PreserveSig]

        int SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);

 

        [PreserveSig]

        int SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);

 

        [PreserveSig]

        int Resolve(IntPtr hwnd, uint fFlags);

 

        [PreserveSig]

        int SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);

    }

 

        [Serializable, StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode), BestFitMapping(false)]

        public struct WIN32_FIND_DATAW

        {

            public uint dwFileAttributes;

            public FILETIME ftCreationTime;

            public FILETIME ftLastAccessTime;

            public FILETIME ftLastWriteTime;

            public uint nFileSizeHigh;

            public uint nFileSizeLow;

            public uint dwReserved0;

            public uint dwReserved1;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]

            public string cFileName;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]

            public string cAlternateFileName;

        }

 

        [Serializable, StructLayout(LayoutKind.Sequential)]

        public struct FILETIME

        {

            public uint dwLowDateTime;

            public uint dwHighDateTime;

        }

 

  上面的定义可以参照VC中的IShellLinkW定义得到。那么,我们就可以把前面创建的IShellLink实例对象转化为IShellLinkW了:

 

IShellLinkW psl = Marshal.GetObjectForIUnknown(ppsl) as IShellLinkW;

 

  然后设置你想获取PIDL的目标路径,以C:\WINDOWS\regedit.exe为例:

 

psl.SetPath(@"C:\WINDOWS\regedit.exe");

 

IntPtr pidl = IntPtr.Zero;

psl.GetIDList(out pidl);

 

  这样,我们就拿到了C:\WINDOWS\regedit.exe的PIDL,保存在IntPtr类型的pidl变量中。接下来就是让SHOpenFolderAndSelectItems方法使用这个PIDL了:

 

SHOpenFolderAndSelectItems(pidl, 0, null, 0);

 

  执行了上面这句代码后,如无意外,Windows就会打开C:\WINDOWS目录,并且选中regedit.exe文件了。最后要做的事情就是清理内存和释放对象:

 

Marshal.FreeCoTaskMem(pidl);

Marshal.Release(ppsl);

 

  主要的功能实现就已经讲完了,如果你要测试,也不难,把上面讲到过的代码合并起来就应该可以执行了。为了方便使用,你可以把它写成一个方法,哪里需要就调用一下即可。

 

  水平有限,文中难免有错或不足,请不吝赐教。

 

  原作:秋忆

  博客:http://qiuyi21.cnblogs.com

 

转:https://www.cnblogs.com/qiuyi21/archive/2009/06/24/1510592.html



推荐阅读
  • 包含phppdoerrorcode的词条 ... [详细]
  • 如何在C#中配置组合框的背景颜色? ... [详细]
  • 开机自启动的几种方式
    0x01快速自启动目录快速启动目录自启动方式源于Windows中的一个目录,这个目录一般叫启动或者Startup。位于该目录下的PE文件会在开机后进行自启动 ... [详细]
  • 本文探讨了如何在C#应用程序中通过选择ComboBox项从MySQL数据库中检索数据值。具体介绍了在事件处理方法 `comboBox2_SelectedIndexChanged` 中可能出现的常见错误,并提供了详细的解决方案和优化建议,以确保数据能够正确且高效地从数据库中读取并显示在界面上。此外,还讨论了连接字符串的配置、SQL查询语句的编写以及异常处理的最佳实践,帮助开发者避免常见的陷阱并提高代码的健壮性。 ... [详细]
  • 本文介绍了如何将包含复杂对象的字典保存到文件,并从文件中读取这些字典。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 在 CentOS 6.4 上安装 QT5 并启动 Qt Creator 时,可能会遇到缺少 GLIBCXX_3.4.15 的问题。这是由于系统中的 libstdc++.so.6 版本过低。本文将详细介绍如何通过更新 GCC 版本来解决这一问题。 ... [详细]
  • 如果应用程序经常播放密集、急促而又短暂的音效(如游戏音效)那么使用MediaPlayer显得有些不太适合了。因为MediaPlayer存在如下缺点:1)延时时间较长,且资源占用率高 ... [详细]
  • DAO(Data Access Object)模式是一种用于抽象和封装所有对数据库或其他持久化机制访问的方法,它通过提供一个统一的接口来隐藏底层数据访问的复杂性。 ... [详细]
  • 在Delphi7下要制作系统托盘,只能制作一个比较简单的系统托盘,因为ShellAPI文件定义的TNotifyIconData结构体是比较早的版本。定义如下:1234 ... [详细]
  • 为了优化用户体验,本文探讨了如何调整下拉菜单的宽度。通过合理设置宽度,可以提升界面的美观性和易用性。文章提供了具体的代码示例,帮助开发者实现这一目标。例如,可以通过 CSS 或 JavaScript 来动态调整下拉菜单的宽度,确保其在不同设备和屏幕尺寸上都能保持良好的显示效果。 ... [详细]
  • 数字图书馆近期展出了一批精选的Linux经典著作,这些书籍虽然部分较为陈旧,但依然具有重要的参考价值。如需转载相关内容,请务必注明来源:小文论坛(http://www.xiaowenbbs.com)。 ... [详细]
  • C# .NET 4.1 版本大型信息化系统集成平台中的主从表事务处理标准示例
    在C# .NET 4.1版本的大型信息化系统集成平台中,本文详细介绍了主从表事务处理的标准示例。通过确保所有操作要么全部成功,要么全部失败,实现主表和关联子表的同步插入。主表插入时会返回当前生成的主键,该主键随后用于子表插入时的关联。以下是一个示例代码片段,展示了如何在一个数据库事务中同时添加角色和相关用户。 ... [详细]
  • 在第10天的夜灵HTML日志中,我们深入探讨了浏览器兼容性和高级选择器的应用。CSS3引入了许多新属性,但在旧版浏览器中的支持情况并不理想。然而,目前主流浏览器的最新版本已全面支持这些新特性。对于那些不支持CSS3新属性的浏览器,我们提供了多种解决方案,以确保网站在不同环境下的兼容性和用户体验。此外,我们还详细讨论了如何利用高级选择器提升页面布局的灵活性和可维护性。 ... [详细]
  • 如何将PHP文件上传至服务器及正确配置服务器地址 ... [详细]
author-avatar
遗忘的睡骨
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有