How to get the associated icon from a network share file

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.


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.


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

Tags:

.Net

Winforms