2009-07-02 14 views
19

W Bibliotece Windows Media Player możesz wybrać jeden lub więcej plików muzycznych. Następnie możesz kliknąć prawym przyciskiem myszy iw menu kontekstowym wybrać Lokalizacja pliku otwartego. Otworzy się jedno okno eksploratora Windows dla każdego katalogu, w którym znajdują się pliki, a pliki zostaną dla ciebie wybrane.C#: Jak otworzyć okna Eksploratora Windows z wybraną liczbą plików

Więc powiedzmy, że mamy kilka plików mp3 w naszej bibliotece, gdzie trzy z nich są następujące:

  • Z: \ Muzyka \ czwartek Blues \ 01. Szkoda, że ​​to nie był piątek.mp3
  • Z: \ Music \ Counting Sheep \ 01. Owca # 1.mp3
  • Z: \ Music \ Counting Sheep \ 02. Owce # 2.mp3

Jeśli mamy wybrać te trzy (w widoku, gdzie wszystkie z nich są widoczne) i zrobić Otwórz lokalizację pliku następnie dwa okna Explorer będzie pop-up. Jednym z nich będzie folder Z: \ Music \ Thursday Blues. Życzę sobie, aby został wybrany piątek.mp3 wybrany, a drugi będzie folderem * Z: \ Music \ Counting Sheep ** zarówno z 01 OwieC# 1.mp3 i 02. Owca # 2.mp3 wybrana.

Jak mogę to zrobić samodzielnie w C#? Mamy aplikację, która będzie eksportować dane do różnych formatów, na przykład CSV i Excel, i chciałbym otworzyć okna eksploratora z tymi plikami wybranymi, gdy zostaną utworzone i gotowe do wyświetlenia. Obecnie po prostu robię Process.Start(path), a to działa, ale chciałbym móc również podświetlić te konkretne pliki. Sprawiłoby, że pliki, które zostały utworzone, były bardziej oczywiste.


Windows Media Player robi to tak dobrze ... Chcę to zrobić zbyt =/Czy istnieją pracownicy tutaj Microsoft, który może dowiedzieć się, w jaki sposób można to zrobić? (A)

Odpowiedz

36

Poszukując odpowiedzi po tym, jak współpracownik miał problem, nie znalazłem żadnego, więc napisałem małą klasę, aby to zrobić. Kod is on Gist i wkleję aktualną wersję na końcu tego postu.

z plikami przykładowych, składnia będzie:

ShowSelectedInExplorer.FilesOrFolders(
    @"Z:\Music\Thursday Blues\01. I wish it was friday.mp3", 
    @"Z:\Music\Counting Sheep\01. Sheep #1.mp3", 
    @"Z:\Music\Counting Sheep\02. Sheep #2.mp3" 
    ); 

Istnieją pewne ograniczenia co do mojego kodu w porównaniu do niskiego API poziomu, głównie:

  • wybierz na pulpicie nie jest realizowany
  • Katalog nadrzędny musi być katalogiem lub dyskiem, więc nie można na przykład wybrać wielu dysków w folderze Mój komputer.

W każdym razie, tutaj jest kod źródłowy klasy ShowSelectedInExplorer:

namespace SHOpenFolderAndSelectItems 
{ 
    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] 
     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] 
     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)] 
     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); 
     } 

     static class NativeMethods 
     { 
      [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 = SHOpenFolderAndSelectItems_(pidlFolder, cidl, apidl, dwFlags); 
       Marshal.ThrowExceptionForHR(result); 
      } 

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

     static IntPtr GetShellFolderChildrenRelativePIDL(IShellFolder parentFolder, string displayName) 
     { 
      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 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) 
      { 
       var 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 
         (string.Format("The specified file or folder doesn't exists : {0}", 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); 
       var filesPidl = filenames 
        .Select(filename => GetShellFolderChildrenRelativePIDL(parent, filename)) 
        .ToArray(); 

       try 
       { 
        SHOpenFolderAndSelectItems(parentPidl, filesPidl, 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) 
     { 
      if (paths == null) throw new ArgumentNullException("paths"); 

      FilesOrFolders(PathToFileSystemInfo(paths)); 
     } 

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

      var explorerWindows = pathsArray.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()); 
      } 
     } 
    } 

    class Program 
    { 
     static void Main() 
     { 

      var test = 3; 
      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(@"C:\Windows\Microsoft.NET\", @"C:\Windows\System32", @"C:\Windows\Setup", @"C:\Program Files"); 
        break; 
      } 
     } 
    } 
} 
+0

Czy to działa z większą liczbą plików rozłożonych w więcej niż jednym oknie teczka? – Svish

+0

Naprawiłem kod, aby dodać tę funkcjonalność, teraz otwiera się w tym przypadku wiele okien eksploratora. –

+0

Fajnie, dziękuję! –

1

Spróbuj uruchomić to:

explorer.exe /select,Z:\Music\Thursday Blues\01. I wish it was friday.mp3 
+2

Works dla jednego pliku, ale w jaki sposób to zrobić dla więcej niż jednego? – Svish

21

Zastrzeżenie: Myślę VirtualBlackFox's answer jest lepsze niż moje, choć ma mniej głosów w chwili obecnej, więc przewinąć w dół i przeczytać pierwszy jeden :)

Prosta metoda (może nie działać na wszystkich platformach):

Process.Start(String, String) 

pierwszy argument jest aplikacja, drugi argument jest th e parametry wiersza polecenia z aplikacji ..

Tak na przykład:

Process.Start("explorer.exe", 
"/select,Z:\Music\Thursday Blues\01. I wish it was friday.mp3") 

Process.Start("explorer.exe", 
"/select,Z:\Music\Counting Sheep\01. Sheep #1.mp3 /select,Z:\Music\Counting Sheep\02. Sheep #2.mp3") 

(myślę, że być może trzeba uciec cudzysłowy wokół ścieżki dostępu do plików, jeśli mają spacje).

więcej info: http://msdn.microsoft.com/en-us/library/h6ak8zt5.aspx

(skompilowany z kilkoma odpowiedziami do this question)


Harder metoda, ale bardziej prawdopodobne, aby pracować, zaczerpnięte z this answer to another question:

użyć funkcji powłoki SHOpenFolderAndSelectItems

Oto przykładowy kod pokazujący, jak korzystać z funkcji w C/C++, bez sprawdzania błędów:

//Directory to open 
ITEMIDLIST *dir = ILCreateFromPath(_T("C:\\")); 

//Items in directory to select 
ITEMIDLIST *item1 = ILCreateFromPath(_T("C:\\Program Files\\")); 
ITEMIDLIST *item2 = ILCreateFromPath(_T("C:\\Windows\\")); 
const ITEMIDLIST* selection[] = {item1,item2}; 
UINT count = sizeof(selection)/sizeof(ITEMIDLIST); 

//Perform selection 
SHOpenFolderAndSelectItems(dir, count, selection, 0); 

//Free resources 
ILFree(dir); 
ILFree(item1); 
ILFree(item2); 
+0

Ten ostatni nie działa, ponieważ nie ma czegoś takiego jak Process.Start (ciąg, ciąg, ciąg). Czy argumenty te powinny być w tym samym ciągu lub coś takiego? – Svish

+0

Tak, masz rację. Zrozumiałem po tym, jak odpowiedziałem i zaktualizowałem odpowiedź; czy to działa teraz? –

+0

Hm. Działa, ale otwiera tylko jedno okno eksploratora z pierwszym wybranym plikiem. – Svish

0

Może można użyć ProcessExplorer, aby dowiedzieć się, które argumenty są używane, gdy program explorer.exe jest uruchamiany z programu Media Player?

Pozdrawiam,

Sebastiaan

+0

Hm, jak czy można to zrobić? – Svish

+0

Najpierw skonfiguruj eksploratora, aby każda instancja eksploratora została uruchomiona w nowym procesie. Następnie otwórz pliki z poziomu odtwarzacza multimedialnego. W ProcessExplorer powinieneś zobaczyć proces potomny odtwarzacza multimedialnego. Kliknij go dwukrotnie, a pełna linia poleceń powinna zostać wyświetlona gdzieś we właściwościach. –

+0

To jest to, czego próbowałem ... ale nie ma nowej instancji eksploratora: S Czy system Windows 7 ignoruje to ustawienie czy coś takiego? – Svish

Powiązane problemy