Retrieving A File’s Shell Icon In C#

Whilst developing my replacement file explorer for my University project, I came across the need to get the Shell Icon for a given file in C#. It took me a while to find out how to accomplish this, so I thought I would post it here for anyone else who is facing the same problem.

First of all, I would suggest creating a new class – I called it SimpleShell.

Secondly, you need to setup three constants needed later on for retrieving the small and large Shell Icons.

public const uint SHGFI_ICON = 0x100;
public const uint SHGFI_LARGEICON = 0x0;
public const uint SHGFI_SMALLICON = 0x1;

Next, your going to want to create a SHFILEINFO struct, like so.

[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
     public IntPtr hIcon;
     public IntPtr iIcon;
     public uint dwAttributes;

     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
     public string szDisplayName;
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
     public string szTypeName;
}

This basically allows you to get a reference to the file in a way that allows you to access it’s Shell properties.

You then want to create a reference to the external methods, SHGetFileInfo and DestroyIcon.

[DllImport('shell32.dll')]
public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);
[DllImport('User32.dll')]
public static extern int DestroyIcon(IntPtr hIcon);

After that, your ready to create your method to return the file’s Shell Icon. The way I do this, is have a generic private method and two public methods (One for retrieving the small icon, and one for the large).

public static Icon GetSmallIcon(string fileName)
{
     return GetIcon(fileName, SHGFI_SMALLICON);
}
public static Icon GetLargeIcon(string fileName)
{
     return GetIcon(fileName, SHGFI_LARGEICON);
}
private static Icon GetIcon(string fileName, uint flags)
{
     var shinfo = new SHFILEINFO();
     var hImgSmall = SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), SHGFI_ICON | flags);
     var icon = (Icon)Icon.FromHandle(shinfo.hIcon).Clone();
     DestroyIcon(shinfo.hIcon);
     return icon;
}

And that’s it, your done!

As an example, if you wanted to get the Shell Icon for Notepad.exe you would call:

Icon notepadIconSmall = SimpleShell.GetSmallIcon(@'C:\WINDOWS\NOTEPAD.EXE');
Icon notepadIconLarge = SimpleShell.GetLargeIcon(@'C:\WINDOWS\NOTEPAD.EXE');

Hope this helps some of you out there! If you have any questions or comments, please leave them below! :)

Leave a Reply

This site uses KeywordLuv. Enter YourName@YourKeywords in the Name field to take advantage.