2010-06-10 9 views
5

Ai đó có thể đưa ra một ví dụ về cách sử dụng hàm vỏ SHOpenFolderAndSelectItems từ C#? Tôi hoàn toàn không có được cách sử dụng các loại chức năng và không thể tìm thấy nó trên pinvoke.net ... =/C#: Cách sử dụng SHOpenFolderAndSelectItems

Nói rằng tôi đã ba tác phẩm được gọi là

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

sau đó tôi muốn mở thư mục X:\Pictures với a.jpg, s.jpg và chọn d.jpg.

Trả lời

-1

Hầu hết các nhu cầu của sẽ SHOpoenFolderSelectedItems sẽ được xử lý bởi:

Đối với lựa chọn tập tin trong C# bạn thường sử dụng: System.Windows.Forms.OpenFileDialog.

Để chọn thư mục trong C#, bạn thường sử dụng: System.Windows.Forms.FolderBrowserDialog.

Bạn sẽ đặt bộ lọc phù hợp và ban đầu bạn có thể đặt mục đã chọn.

Có lẽ điều này đủ gần với những gì bạn cần?

+0

Không, những điều tôi biết.Họ là để lựa chọn thư mục hoặc tập tin để mở trong ứng dụng của bạn. Những gì tôi muốn là để mở cửa sổ thám hiểm từ ứng dụng của tôi với các tập tin được chọn. Giống như bạn có thể làm trong ví dụ như Windows Media Player, nơi bạn có thể đánh dấu một số tệp, nhấp chuột phải và nhấp vào "Hiển thị trong Explorer" hoặc những gì nó nói ở đó. Khi bạn làm điều đó, một cửa sổ thám hiểm sẽ mở ra với tất cả các tệp được chọn mà bạn đã chọn trong WMP. – Svish

0

Kiểm tra http://www.cnblogs.com/qiuyi21/archive/2009/06/24/1510592.html. Ví dụ sử dụng IShellLink để lấy các pidls từ đường dẫn trước khi khởi chạy SHOpenFolderAndSelectItems, thay vào đó tôi sẽ sử dụng ILCreateFromPath.

+2

Hm, tôi không đọc Chineese, hehe. Dù sao, bạn có thể tạo một ví dụ đơn giản về việc sử dụng ILCreateFromPath và SHOpenFolderAndSelectItems để chọn 3 tệp tôi đã đề cập trong câu hỏi của mình không? – Svish

6

Có vẻ như bạn đã hỏi hai lần cùng một câu hỏi (câu hỏi khác là C#: How to open Windows Explorer windows with a number of files selected không có câu trả lời) Tôi đăng giải pháp của mình cho cả hai câu hỏi mà tôi không biết mình có nên tạo một cộng đồng wiki hay không.

Tìm kiếm câu trả lời sau khi đồng nghiệp có vấn đề tôi không tìm thấy nên tôi đã viết một lớp nhỏ để thực hiện việc này. Mã số is on Gist và tôi sẽ dán phiên bản hiện tại vào cuối bài đăng này.

Với file mẫu của bạn, cú pháp sẽ là:

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

Có một số hạn chế đối với mã của tôi so với các API cấp thấp, chủ yếu là:

  • Lựa chọn trên desktop không được thực hiện
  • Thư mục mẹ phải là một thư mục hoặc một ổ đĩa, vì vậy bạn không thể chọn nhiều ổ đĩa trong thư mục My Computer chẳng hạn.

Dù sao, đây là ShowSelectedInExplorer mã nguồn lớp:

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

Điều này giống như giải pháp cho vấn đề của tôi. Bạn có thể giải thích cách tôi thực sự sử dụng mã đó không? Tôi tưởng tượng nó không phải là một cái gì đó tôi chỉ có thể đặt trên một tập tin .bat hoặc .vbs ... Cảm ơn. –

+0

Vì thẻ C# ngụ ý đó là lớp C# và nó yêu cầu phải xây dựng bằng trình biên dịch C# và được gọi từ chương trình hoặc thư viện C#. –

3

Không phải là một câu trả lời 100%, nhưng đoạn này cho thấy làm thế nào để chọn một mục duy nhất trong nhà thám hiểm từ 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

Cảm ơn, nhưng đó là một trong những loại tôi tìm ra trên của riêng tôi;) – Svish

+0

cảm ơn, đã làm việc cho tôi để duyệt các tập tin trong mạng – AVEbrahimi