3

I'm using the ExtractAssociatedIcon method to retrieve the icon for the file. My hope is to retrieve the same icon that a user would see in their explorer window.

    public static Icon GetIcon(string fileName) 
    {
        try
        {
            Icon icon = Icon.ExtractAssociatedIcon(fileName);
            return icon;
        }
        catch
        {
            return null;
        }
    }

This works 99% of the time. However, if the user has linked to a file on a shared path, such as \\SOME_SERVER\my documents\this file.pdf it returns null. It falls through the "catch" with the error that the file path is not a valid path.

It is a valid URI (I've verified the file exists, is readable, etc.), but not a valid fully-qualified drive path with the X:\some\folder notation.

How can I get around this, if at all?

Thanks.

Re-UPDATE

Here's the solution I ended up with. It's much cleaner than the first update. Many thanks to Chris Haas, whose answer was a comment, and not a direct answer. If/when he makes it a direct answer, I will update this as such.

I still had to go down to a lower level and fetch the icon through C++ libraries, but the only library I needed is listed below:

    #region Old-School method
    [DllImport("shell32.dll")]
    static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, 
       StringBuilder lpIconPath, out ushort lpiIcon);

    public static Icon GetIconOldSchool(string fileName)
    {
        ushort uicon;
        StringBuilder strB = new StringBuilder(fileName);
        IntPtr handle = ExtractAssociatedIcon(IntPtr.Zero, strB, out uicon);
        Icon ico = Icon.FromHandle(handle);

        return ico;
    }
    #endregion

Once I had defined the above method, the GetIcon() method becomes:

    public static Icon GetIcon(string fileName) 
    {
        try
        {
            Icon icon = Icon.ExtractAssociatedIcon(fileName);
            return icon;
        }
        catch
        {
            try
            {
                Icon icon2 = GetIconOldSchool(fileName);
                return icon2;
            }
            catch
            {
                return null;
            }
        }
    }
John Saunders
  • 160,644
  • 26
  • 247
  • 397
Jerry
  • 4,507
  • 9
  • 50
  • 79
  • 1
    possible duplicate of [How to get the associated icon from a network share file](http://stackoverflow.com/questions/1842226/how-to-get-the-associated-icon-from-a-network-share-file) – Chris Haas Jul 25 '11 at 16:44
  • 1
    MSDN documentation for `ExtractAssociatedIcon` says that an `ArgumentException` will be thrown if `The filePath indicates a Universal Naming Convention (UNC) path.` http://msdn.microsoft.com/en-us/library/system.drawing.icon.extractassociatedicon.aspx – Chris Haas Jul 25 '11 at 17:09
  • True. But that doesn't help me with how to get the icon. =) Any suggestions on that front? – Jerry Jul 25 '11 at 17:21
  • The link in my first comment will give you a much shorter version that will be much cleaner, just two P/Invokes, no enums or constants. – Chris Haas Jul 25 '11 at 17:48
  • Put that as an answer so that I can mark it as such.... and you get the credit. That worked very well! – Jerry Jul 25 '11 at 18:08

1 Answers1

2

(Comment turned into post - CTIP)

Check out the link here which eventually leads to P/Invoke.net with the following code:

[DllImport("shell32.dll")]
static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, StringBuilder lpIconPath, out ushort lpiIcon);

[DllImport("shell32.dll")]
static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex);

_

ushort uicon;
StringBuilder strB = new StringBuilder(YOUR_FILE_PATH);
IntPtr handle = ExtractAssociatedIcon(this.Handle, strB, out uicon);
Icon ico = Icon.FromHandle(handle);

return ico.ToBitmap();
Community
  • 1
  • 1
Chris Haas
  • 53,986
  • 12
  • 141
  • 274