Find an application’s icon with WinAPI

Tags:

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);
  else
    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);