Find an application’s icon with WinAPI


I was working on some C# code today, and had to figure out how to find a specific application’s icon.

There’s a lot of basic information on this, including messages like WM_GETICON in MSDN, but it just wouldn’t work.

One of the reasons I like C# is how it makes doing things easy, and it’s also very easy to figure out how to do something that you haven’t done before with it.

The thing I dislike in C/C++ is that it’s so damn difficult to figure out at times, especially some things, such as this one. Sure, there’s a lot of documentation available about the Windows API, but how do I know where to look?

I did eventually figure out how to do this, so here’s the solution for anyone else who might be struggling with the same

public Icon GetAppIcon(IntPtr hwnd)
  IntPtr iconHandle = SendMessage(hwnd,WM_GETICON,ICON_SMALL2,0);
  if(iconHandle == IntPtr.Zero)
    iconHandle = SendMessage(hwnd,WM_GETICON,ICON_SMALL,0);
  if(iconHandle == IntPtr.Zero)
    iconHandle = SendMessage(hwnd,WM_GETICON,ICON_BIG,0);
  if (iconHandle == IntPtr.Zero)
    iconHandle = GetClassLongPtr(hwnd, GCL_HICON);
  if (iconHandle == IntPtr.Zero)
    iconHandle = GetClassLongPtr(hwnd, GCL_HICONSM);
  if(iconHandle == IntPtr.Zero)
    return null;
  Icon icn = Icon.FromHandle(iconHandle);
  return icn;

The constants and other methods used:

public const int GCL_HICONSM = -34;
public const int GCL_HICON = -14;
public const int ICON_SMALL = 0;
public const int ICON_BIG = 1;
public const int ICON_SMALL2 = 2;
public const int WM_GETICON = 0x7F;
public static IntPtr GetClassLongPtr(IntPtr hWnd, int nIndex)
  if (IntPtr.Size > 4)
    return GetClassLongPtr64(hWnd, nIndex);
    return new IntPtr(GetClassLongPtr32(hWnd, nIndex));
[DllImport("user32.dll", EntryPoint = "GetClassLong")]
public static extern uint GetClassLongPtr32(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", EntryPoint = "GetClassLongPtr")]
public static extern IntPtr GetClassLongPtr64(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);