C#打开目录并选中文件(夹)的实现
2010-06-06 15:26
489 查看
没错,就是想实现像上图中点击“查找目标”按钮一样的功能,即是打开目录并选中文件(夹)。有人可能会问,使用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);
主要的功能实现就已经讲完了,如果你要测试,也不难,把上面讲到过的代码合并起来就应该可以执行了。为了方便使用,你可以把它写成一个方法,哪里需要就调用一下即可。
相关文章推荐
- C#打开目录并选中文件(夹)的实现
- QT实现打开文件目录并选中文件
- C#实现打开文件或文件夹及选中文件
- Qt工程实现打开目录并选中指定文件的方法
- QT实现打开文件所在目录并选中文件
- C#实现同一个对话框打开目录和文件
- C# 操作注册表,实现记住上次打开的文件目录
- C# 打开目录并选中文件的相关问题
- C#实现打开文件或文件夹及选中文件
- Qt工程实现打开目录并选中指定文件的方法
- C# API 打开目录并选中文件(夹)的实现
- Qt工程实现打开目录并选中指定文件的方法
- C#实现打开文件或文件夹及选中文件
- c++编程实现指定目录下,捕获文件打开事件 。目录上锁
- C#打开指定文件或目录
- C#实现文件拖放并打开文件(使用ListBox)
- C# 打开指定目录并定位到文件
- window打开指定目录下文件并选中
- C#实现的列出目录下所有子目录和文件的程序(附思路)
- sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)