Get the file icon used by Shell

In .Net (C # or VB: don't care), given the file path string, FileInfo structure or FileSystemInfo structure for a real existing file, how can I determine the icon used by the shell (explorer) for this file?

I currently do not plan to use this for anything, but I was curious how to do this when viewing this question , and I thought it would be useful for archiving here on SO.

+42
c # winforms
Jan 20 '09 at 17:30
source share
9 answers
Imports System.Drawing Module Module1 Sub Main() Dim filePath As String = "C:\myfile.exe" Dim TheIcon As Icon = IconFromFilePath(filePath) If TheIcon IsNot Nothing Then ''#Save it to disk, or do whatever you want with it. Using stream As New System.IO.FileStream("c:\myfile.ico", IO.FileMode.CreateNew) TheIcon.Save(stream) End Using End If End Sub Public Function IconFromFilePath(filePath As String) As Icon Dim result As Icon = Nothing Try result = Icon.ExtractAssociatedIcon(filePath) Catch ''# swallow and return nothing. You could supply a default Icon here as well End Try Return result End Function End Module 
+50
Jan 20 '09 at 17:40
source share

Please ignore anyone who tells you to use the registry! The registry is not an API. The API you want is SHGetFileInfo with SHGFI_ICON. Here you can get the P / Invoke signature:

http://www.pinvoke.net/default.aspx/shell32.SHGetFileInfo

+15
Jan 20 '09 at 18:24
source share

You must use SHGetFileInfo.

Icon.ExtractAssociatedIcon works like SHGetFileInfo in most cases, but SHGetFileInfo can work with UNC paths (for example, a network path like "\\ ComputerName \ SharedFolder \"), while Icon.ExtractAssociatedIcon cannot. If you need or may need to use UNC paths, it is better to use SHGetFileInfo instead of Icon.ExtractAssociatedIcon.

This is a good CodeProject article on how to use SHGetFileInfo.

+14
May 05 '09 at 2:26 a.m.
source share

No more than a C # version of Stefan's answer.

 using System.Drawing; class Class1 { public static void Main() { var filePath = @"C:\myfile.exe"; var theIcon = IconFromFilePath(filePath); if (theIcon != null) { // Save it to disk, or do whatever you want with it. using (var stream = new System.IO.FileStream(@"c:\myfile.ico", System.IO.FileMode.CreateNew)) { theIcon.Save(stream); } } } public static Icon IconFromFilePath(string filePath) { var result = (Icon)null; try { result = Icon.ExtractAssociatedIcon(filePath); } catch (System.Exception) { // swallow and return nothing. You could supply a default Icon here as well } return result; } } 
+5
Oct 18 '13 at 8:08
source share

This works for me in my projects, hope this helps someone.

This is C # with P / Invokes, it will still work on x86 / x64 systems with WinXP.

(Shell.cs)

 using System; using System.Drawing; using System.IO; using System.Runtime.InteropServices; namespace IconExtraction { internal sealed class Shell : NativeMethods { #region OfExtension ///<summary> /// Get the icon of an extension ///</summary> ///<param name="filename">filename</param> ///<param name="overlay">bool symlink overlay</param> ///<returns>Icon</returns> public static Icon OfExtension(string filename, bool overlay = false) { string filepath; string[] extension = filename.Split('.'); string dirpath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "cache"); Directory.CreateDirectory(dirpath); if (String.IsNullOrEmpty(filename) || extension.Length == 1) { filepath = Path.Combine(dirpath, "dummy_file"); } else { filepath = Path.Combine(dirpath, String.Join(".", "dummy", extension[extension.Length - 1])); } if (File.Exists(filepath) == false) { File.Create(filepath); } Icon icon = OfPath(filepath, true, true, overlay); return icon; } #endregion #region OfFolder ///<summary> /// Get the icon of an extension ///</summary> ///<returns>Icon</returns> ///<param name="overlay">bool symlink overlay</param> public static Icon OfFolder(bool overlay = false) { string dirpath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "cache", "dummy"); Directory.CreateDirectory(dirpath); Icon icon = OfPath(dirpath, true, true, overlay); return icon; } #endregion #region OfPath ///<summary> /// Get the normal,small assigned icon of the given path ///</summary> ///<param name="filepath">physical path</param> ///<param name="small">bool small icon</param> ///<param name="checkdisk">bool fileicon</param> ///<param name="overlay">bool symlink overlay</param> ///<returns>Icon</returns> public static Icon OfPath(string filepath, bool small = true, bool checkdisk = true, bool overlay = false) { Icon clone; SHGFI_Flag flags; SHFILEINFO shinfo = new SHFILEINFO(); if (small) { flags = SHGFI_Flag.SHGFI_ICON | SHGFI_Flag.SHGFI_SMALLICON; } else { flags = SHGFI_Flag.SHGFI_ICON | SHGFI_Flag.SHGFI_LARGEICON; } if (checkdisk == false) { flags |= SHGFI_Flag.SHGFI_USEFILEATTRIBUTES; } if (overlay) { flags |= SHGFI_Flag.SHGFI_LINKOVERLAY; } if (SHGetFileInfo(filepath, 0, ref shinfo, Marshal.SizeOf(shinfo), flags) == 0) { throw (new FileNotFoundException()); } Icon tmp = Icon.FromHandle(shinfo.hIcon); clone = (Icon)tmp.Clone(); tmp.Dispose(); if (DestroyIcon(shinfo.hIcon) != 0) { return clone; } return clone; } #endregion } } 

(NativeMethods.cs)

 using System; using System.Drawing; using System.Runtime.InteropServices; namespace IconExtraction { internal class NativeMethods { public struct SHFILEINFO { public IntPtr hIcon; public int iIcon; public uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; [DllImport("user32.dll")] public static extern int DestroyIcon(IntPtr hIcon); [DllImport("shell32.dll", CharSet = CharSet.Auto, BestFitMapping = false, ThrowOnUnmappableChar = true)] public static extern IntPtr ExtractIcon(IntPtr hInst, string lpszExeFileName, int nIconIndex); [DllImport("Shell32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true)] public static extern int SHGetFileInfo(string pszPath, int dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, SHGFI_Flag uFlags); [DllImport("Shell32.dll")] public static extern int SHGetFileInfo(IntPtr pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, int cbFileInfo, SHGFI_Flag uFlags); } public enum SHGFI_Flag : uint { SHGFI_ATTR_SPECIFIED = 0x000020000, SHGFI_OPENICON = 0x000000002, SHGFI_USEFILEATTRIBUTES = 0x000000010, SHGFI_ADDOVERLAYS = 0x000000020, SHGFI_DISPLAYNAME = 0x000000200, SHGFI_EXETYPE = 0x000002000, SHGFI_ICON = 0x000000100, SHGFI_ICONLOCATION = 0x000001000, SHGFI_LARGEICON = 0x000000000, SHGFI_SMALLICON = 0x000000001, SHGFI_SHELLICONSIZE = 0x000000004, SHGFI_LINKOVERLAY = 0x000008000, SHGFI_SYSICONINDEX = 0x000004000, SHGFI_TYPENAME = 0x000000400 } } 
+4
Jun 10 '14 at 16:46
source share

The problem with the registry approach is that you are clearly not getting the icon index identifier. Sometimes (if not all times) you get a ResourceID badge, which is an alias of the application developer used to designate the slot icon.

Therefore, the registry method implies that all developers use ResourceIDs that match the implicit icon identifier index (which is zero-based, absolute, deterministic).

Scan the registry location and you will see many negative numbers, sometimes even text links, i.e. not an icon index identifier. The implicit method seems to be better because it allows the OS to do the work.

Only testing this new method now, but it makes sense and hopefully solves this problem.

+1
Jul 27 '11 at 19:49
source share

If you are only interested in the icon for a specific extension, and if you do not mind creating a temporary file, you can follow the example below here

C # code:

  public Icon LoadIconFromExtension(string extension) { string path = string.Format("dummy{0}", extension); using (File.Create(path)) { } Icon icon = Icon.ExtractAssociatedIcon(path); File.Delete(path); return icon; } 
+1
Jun 29 2018-12-12T00:
source share

This link seems to contain some information. This is due to a lot of registry changes, but it seems doable. Examples are given in C ++

0
Jan 20 '09 at 17:42
source share
  • define extension
  • in the registry, go to "HKCR\.{extension}" , read the default value (call it filetype )
  • in "HKCR\{filetype}\DefaultIcon" , read the default value: this is the path to the icon file (or the icon container file, for example .exe with an embedded icon resource)
  • if necessary, use the preferred method of extracting the icon resource from the specified file.

edit / move away from comments:

If the icon is in the container file (this is quite common), there will be a counter after the path, for example: "foo.exe,3" . This means that icon 4 icon (index based on zero value) of available icons. The value ", 0" is implicit (and optional). If the counter is 0 or missing, the fist icon will be used by the shell.

0
Jan 20 '09 at 17:48
source share



All Articles