Created
August 26, 2010 15:33
-
-
Save vbfox/551626 to your computer and use it in GitHub Desktop.
Sample code for SHOpenFolderAndSelectItems in C#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
namespace SHOpenFolderAndSelectItems | |
{ | |
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)] | |
internal 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] IntPtr apidl, int dwFlags | |
); | |
public static void SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, int dwFlags) | |
{ | |
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 void SHOpenFolderAndSelectItems(IntPtr pidlFolder, ICollection<IntPtr> apidl, bool edit) | |
{ | |
IntPtr array = IntPtr.Zero; | |
uint itemCount = 0; | |
try | |
{ | |
if (apidl != null && apidl.Count > 0) | |
{ | |
itemCount = (uint)apidl.Count; | |
array = Marshal.AllocHGlobal(pointerSize * apidl.Count); | |
var i = 0; | |
foreach (var filePIDL in apidl) | |
{ | |
Marshal.WriteIntPtr(array, i * pointerSize, filePIDL); | |
i++; | |
} | |
} | |
NativeMethods.SHOpenFolderAndSelectItems(pidlFolder, itemCount, array, edit ? 1 : 0); | |
} | |
finally | |
{ | |
Marshal.FreeHGlobal(array); | |
} | |
} | |
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, IntPtr.Zero, ref IID_IShellFolder, out folder); | |
Marshal.ThrowExceptionForHR((int)result); | |
return folder; | |
} | |
static IShellFolder PIDLToShellFolder(IntPtr pidl) | |
{ | |
return PIDLToShellFolder(NativeMethods.SHGetDesktopFolder(), pidl); | |
} | |
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) | |
{ | |
if (Directory.Exists(path)) yield return new DirectoryInfo(path); | |
else yield return new FileInfo(path); | |
} | |
} | |
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, false); | |
} | |
finally | |
{ | |
foreach (var pidl in filesPidl) | |
{ | |
NativeMethods.ILFree(pidl); | |
} | |
} | |
} | |
finally | |
{ | |
NativeMethods.ILFree(parentPidl); | |
} | |
} | |
public static void FilesOrFolders(IEnumerable<string> paths, bool showOnDesktop = false) | |
{ | |
FilesOrFolders(PathToFileSystemInfo(paths), showOnDesktop); | |
} | |
public static void FilesOrFolders(IEnumerable<FileSystemInfo> paths, bool showOnDesktop = false) | |
{ | |
if (paths == null) throw new ArgumentNullException("paths"); | |
if (paths.Count() == 0) return; | |
var parentDirectories = paths.Select(p => Path.GetDirectoryName(p.FullName)); | |
var parentDirectory = parentDirectories.First(); | |
var otherDirectories = parentDirectories.Skip(1); | |
if (otherDirectories.Any(p => p != parentDirectory)) | |
{ | |
throw new ArgumentException("At least one path is not in the same directory as the others", "paths"); | |
} | |
FilesOrFolders(parentDirectory, paths.Select(fsi => fsi.Name).ToList()); | |
} | |
} | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
var test = 1; | |
switch (test) | |
{ | |
case 0: | |
var mydocs = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); | |
ShowSelectedInExplorer.FileOrFolder(Path.Combine(mydocs, "Visual Studio 2010"), edit: true); | |
break; | |
case 1: | |
ShowSelectedInExplorer.FileOrFolder(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)); | |
break; | |
case 2: | |
ShowSelectedInExplorer.FilesOrFolders(@"C:\Windows\", new[] { "Microsoft.NET", "System32", "Setup" }); | |
break; | |
case 3: | |
ShowSelectedInExplorer.FilesOrFolders(new[] { @"C:\Windows\Microsoft.NET", @"C:\Windows\System32", @"C:\Windows\Setup" }); | |
break; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment