1

I'm using following code to get the image using icon path. I think I'm doing all the error checks before returning image. So why this exception. Exception generated on adding received image to image List. Exception is generated on users machine so no way to debug.

private static Icon ExtractIcon(string file, int number, bool largeIcon)
{
    IntPtr large;
    IntPtr small;
    ExtractIconEx(file, number, out large, out small, 1);
    try
    {
        return Icon.FromHandle(largeIcon ? large : small);
    }
    catch
    {
        return null;
    }
}

[DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true,
    CallingConvention = CallingConvention.StdCall)]
private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion,
                                        out IntPtr piSmallVersion, int amountIcons);

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

public static Image GetImage(string icon)
{
    try
    {
        if (!string.IsNullOrEmpty(icon))
        {
            if (icon.Contains(","))
            {
                string[] split = icon.Split(new[] { ',' });
                if (!string.IsNullOrEmpty(split[0]))
                {
                    int index;
                    int.TryParse(split[1], out index);
                    Icon image =
                        ExtractIcon(Environment.ExpandEnvironmentVariables(split[0]).TrimMatchingQuotes('\"'),
                                    index, true);
                    if (image != null)
                        return image.ToBitmap();
                }
            }
            if (File.Exists(icon))
            {
                try
                {
                    Icon image = Icon.ExtractAssociatedIcon(icon);
                    return image != null ? image.ToBitmap() : Resources.picture;
                }
                catch (ArgumentException)
                {
                    var strB = new StringBuilder(icon);
                    ushort uicon;
                    IntPtr handle = ExtractAssociatedIcon(IntPtr.Zero, strB, out uicon);
                    return Icon.FromHandle(handle).ToBitmap();
                }
            }
        }
        return Resources.picture;
    }
    catch (Exception)
    {
        return Resources.picture;
    }
}

private static string TrimMatchingQuotes(this string input, char quote)
{
    if ((input.Length >= 2) &&
        (input[0] == quote) && (input[input.Length - 1] == quote))
        return input.Substring(1, input.Length - 2);

    return input;
}
Ravi Patel
  • 2,136
  • 3
  • 32
  • 48
  • 1
    Icons returned by ExtractIconEx() must be destroyed again by DestroyIcon(). Create a unit test for this code, including the code that uses the returned image. Run the GetMethod() image at least 10,000 times, enough to get your handle leak to start to have side-effects. – Hans Passant Jun 27 '13 at 10:19
  • 1
    You'll find a Reflection hack to get the Icon object to automatically release the handle in [this answer](http://stackoverflow.com/a/1551567/17034). – Hans Passant Jun 27 '13 at 10:25

0 Answers0