How to get the associated icon from a network share file

后端 未结 5 1437
深忆病人
深忆病人 2020-12-07 00:21

I am using Icon.ExtractAssociatedIcon to get the icon of a file , that a user selects, in an openfiledialog.

THe problem is if the user selects an icon from a netw

相关标签:
5条回答
  • 2020-12-07 00:51

    For completeness' sake, here's an ExtractAssociatedIcon routine that works:

    /// <summary>
    /// Returns an icon representation of an image contained in the specified file.
    /// This function is identical to System.Drawing.Icon.ExtractAssociatedIcon, xcept this version works.
    /// </summary>
    /// <param name="filePath">The path to the file that contains an image.</param>
    /// <returns>The System.Drawing.Icon representation of the image contained in the specified file.</returns>
    /// <exception cref="System.ArgumentException">filePath does not indicate a valid file.</exception>
    public static Icon  ExtractAssociatedIcon(String filePath)
    {
        int index = 0;
    
        Uri uri;
        if (filePath == null)
        {
            throw new ArgumentException(String.Format("'{0}' is not valid for '{1}'", "null", "filePath"), "filePath");
        }
        try
        {
            uri = new Uri(filePath);
        }
        catch (UriFormatException)
        {
            filePath = Path.GetFullPath(filePath);
            uri = new Uri(filePath);
        }
        //if (uri.IsUnc)
        //{
        //  throw new ArgumentException(String.Format("'{0}' is not valid for '{1}'", filePath, "filePath"), "filePath");
        //}
        if (uri.IsFile)
        {
            if (!File.Exists(filePath))
            {
                //IntSecurity.DemandReadFileIO(filePath);
                throw new FileNotFoundException(filePath);
            }
    
            StringBuilder iconPath = new StringBuilder(260);
            iconPath.Append(filePath);
    
            IntPtr handle = SafeNativeMethods.ExtractAssociatedIcon(new HandleRef(null, IntPtr.Zero), iconPath, ref index);
            if (handle != IntPtr.Zero)
            {
                //IntSecurity.ObjectFromWin32Handle.Demand();
                return Icon.FromHandle(handle);
            }
        }
        return null;
    }
    
    
    /// <summary>
    /// This class suppresses stack walks for unmanaged code permission. 
    /// (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) 
    /// This class is for methods that are safe for anyone to call. 
    /// Callers of these methods are not required to perform a full security review to make sure that the 
    /// usage is secure because the methods are harmless for any caller.
    /// </summary>
    [SuppressUnmanagedCodeSecurity]
    internal static class SafeNativeMethods
    {
        [DllImport("shell32.dll", EntryPoint = "ExtractAssociatedIcon", CharSet = CharSet.Auto)]
        internal static extern IntPtr ExtractAssociatedIcon(HandleRef hInst, StringBuilder iconPath, ref int index);
    }
    

    Note: Any code is released into the public domain. No attribution required.

    0 讨论(0)
  • 2020-12-07 00:53

    Another option would be to copy the file the user selects to their %TEMP% and use Icon.ExtractAssociatedIcon there. Just remember to cleanup after yourself.

    Obviously not a great solution if you're supporting LARGE files!

    0 讨论(0)
  • 2020-12-07 00:56

    Looking at this with Reflector, it is ultimately calling ExtractAssociatedIcon in shell32.dll.

    Have you tried the going around the BCL accessing it via PInvoke?

    Sample code (via PInvoke.Net):

    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, StringBuilder lpIconPath,
       out ushort lpiIcon);
    
     // ... snip
        ushort uicon;
        StringBuilder strB = new StringBuilder(260); // Allocate MAX_PATH chars
        strB.Append(openFileDialog1.FileName);
        IntPtr handle = ExtractAssociatedIcon(IntPtr.Zero, strB, out uicon);
        Icon ico = Icon.FromHandle(handle);
    
        pictureBox1.Image = ico.ToBitmap();
     // ... snip
    
    0 讨论(0)
  • 2020-12-07 01:06

    Just to complement Ian Boyd answer , if the file is an image, instead of the file icon, you can use FileStream to preview it:

    foreach (string item in Directory.GetFiles(actualPath))
    {
    
        fi = new FileInfo(item);
    
        using (FileStream stream = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read))
         {
              myImageList.Images.Add(Image.FromStream(stream));
    
         }
    }
    
    0 讨论(0)
  • 2020-12-07 01:10

    One method to accomplish this is to retrieve your UNC path and temporarily map it to a drive letter, then use that drive in your .ExtractAssociatedIcon method. When you have retrieved the icon, you can unmap the drive. It's not elegant, but it should work just fine.

    0 讨论(0)
提交回复
热议问题