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!