2010-06-10 14 views
5

¿Podría alguien dar un ejemplo sobre cómo usar la función de shell SHOpenFolderAndSelectItems de C#? Yo no lo entiendo muy cómo utilizar este tipo de funciones y no podía encontrarlo en pinvoke.net ... =/C#: Cómo usar SHOpenFolderAndSelectItems

decir que tengo tres archivos llamados

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

entonces quiero abrir la carpeta X:\Pictures con a.jpg, s.jpg y d.jpg seleccionado.

Respuesta

-1

La mayor parte de las necesidades de SHOpoenFolderSelectedItems haría sería manejado por:

Para la selección de archivos en C# que normalmente se utiliza: System.Windows.Forms.OpenFileDialog.

Para la selección de carpetas en C#, normalmente usaría: System.Windows.Forms.FolderBrowserDialog.

Debería establecer un filtro apropiado y puede establecer inicialmente un elemento seleccionado.

Quizás esto es lo suficientemente cerca de lo que necesita?

+0

No, esos que conozco.Son para seleccionar carpetas o archivos para abrir en su aplicación. Lo que quiero es abrir las ventanas del explorador desde mi aplicación con los archivos seleccionados. Como puede hacer en, por ejemplo, Windows Media Player, donde puede marcar una cantidad de archivos, haga clic derecho y haga clic en "Mostrar en el Explorador" o lo que dice allí. Cuando lo haga, se abrirá una ventana del explorador con todos los archivos seleccionados que haya seleccionado en WMP. – Svish

0

Verificar http://www.cnblogs.com/qiuyi21/archive/2009/06/24/1510592.html. El ejemplo usa IShellLink para obtener los pidls de la ruta de acceso antes de ejecutar SHOpenFolderAndSelectItems, yo usaría ILCreateFromPath en su lugar.

+2

Hm, no leo Chineese, jeje. De todos modos, ¿podría crear un ejemplo simple de uso de ILCreateFromPath y SHOpenFolderAndSelectItems para seleccionar los 3 archivos que mencioné en mi pregunta? – Svish

6

como parece que han pedido dos veces la misma pregunta (el otro es C#: How to open Windows Explorer windows with a number of files selected que no tenía respuesta) he puesto mi solución a ambas preguntas no sé si debería hacer uno un wiki de la comunidad.

Buscando una respuesta después de que un compañero de trabajo tuvo el problema, no encontré ninguno, así que escribí una clase pequeña para hacer esto. El código is on Gist y pegaré la versión actual al final de esta publicación.

Con sus archivos de ejemplo, la sintaxis será:

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

Hay algunas limitaciones a mi código en comparación con la API de bajo nivel, principalmente:

  • Selección en el escritorio no se ha implementado
  • El directorio principal debe ser un directorio o una unidad, por lo que no puede seleccionar varias unidades en la carpeta Mi PC, por ejemplo.

De todos modos, aquí está el código fuente de la clase 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()); 
     } 
    } 
} 
+0

Esto parece ser la solución a un problema mío también. ¿Podría explicarme cómo realmente uso ese código? Me imagino que no es algo que simplemente pueda poner en un archivo .bat o .vbs ... Gracias. –

+0

Como la etiqueta C# implica que es una clase C# y requiere ser compilada usando un compilador C# y llamada desde un programa o biblioteca C#. –

3

No es una respuesta del 100%, pero este fragmento se muestra cómo seleccionar un solo elemento en el explorador de C#.

private void SelectInFileExplorer(string fullPath) 
    { 
     if (string.IsNullOrEmpty(fullPath)) 
      throw new ArgumentNullException("fullPath"); 

     fullPath = Path.GetFullPath(fullPath); 

     IntPtr pidlList = NativeMethods.ILCreateFromPathW(fullPath); 
     if (pidlList != IntPtr.Zero) 
      try 
      { 
       // Open parent folder and select item 
       Marshal.ThrowExceptionForHR(NativeMethods.SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0)); 
      } 
      finally 
      { 
       NativeMethods.ILFree(pidlList); 
      } 
    } 

    static class NativeMethods 
    { 

     [DllImport("shell32.dll", ExactSpelling=true)] 
     public static extern void ILFree(IntPtr pidlList); 

     [DllImport("shell32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)] 
     public static extern IntPtr ILCreateFromPathW(string pszPath); 

     [DllImport("shell32.dll", ExactSpelling=true)] 
     public static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags); 
    } 
+0

Gracias, pero ese que me imaginé por mi cuenta;) – Svish

+0

gracias, me ha funcionado para buscar archivos en la red – AVEbrahimi