C#: How to open Windows Explorer windows with a number of files selected

前端 未结 5 1164
花落未央
花落未央 2020-12-02 09:53

In the Library of Windows Media Player you can select one or more music files. You can then right-click and in their context menu choose Open File Location. This wi

相关标签:
5条回答
  • 2020-12-02 10:35

    Try starting this:

    explorer.exe /select,Z:\Music\Thursday Blues\01. I wish it was friday.mp3
    
    0 讨论(0)
  • 2020-12-02 10:39

    Maybe you can use ProcessExplorer to find out which arguments are used when explorer.exe is launched from Media Player?

    0 讨论(0)
  • 2020-12-02 10:45

    To summarize: It is not possible using Process.Start

    From: programatically-select-multiple-files-in-windows-explorer

    flashk's answer of "This should be possible with the shell function SHOpenFolderAndSelectItems" seems possible to me, but I have not tired it

    This is an old question, but came up first when I was googling similar, so I'm trying to make the conclusion easier to find.

    0 讨论(0)
  • 2020-12-02 10:50

    Searching for an answer after a coworker had the issue i found none so i wrote a small class to do this. The code is on Gist and i will paste the curent version at the end of this post.

    With your sample files, the syntax will be :

    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"
        );
    

    There are some limitations to my code compared to the low level API, mainly :

    • Selecting on the desktop is not implemented
    • The parent directory must be a directory or a drive, so you can't select multiple drives in the My Computer folder for example.

    Anyway, here is the ShowSelectedInExplorer class source code :

    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 讨论(0)
  • 2020-12-02 11:00

    Disclaimer: I think VirtualBlackFox's answer is better than mine although it has less votes at present, so scroll down and read that one first :)

    Easy method (might not work on all platforms):

    Process.Start(String, String)
    

    First argument is the application, second argument is the command line parameters of the application..

    So for example:

    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")
    

    (I think you might need escaped quotes around the file paths if they have spaces).

    more info: http://msdn.microsoft.com/en-us/library/h6ak8zt5.aspx

    (compiled from several answers to this question)


    Harder method, but more likely to work, taken from this answer to another question:

    Use the shell function SHOpenFolderAndSelectItems

    Here is some sample code showing how to use the function in C/C++, without error checking:

    //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 讨论(0)
提交回复
热议问题