Obtener el ícono para una extensión dada

Sé que puedo extraer el ícono de un archivo usando

using (System.Drawing.Icon sysicon = System.Drawing.Icon.ExtractAssociatedIcon(filePath)) { icon = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon( sysicon.Handle, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); } 

Pero, ¿cómo puedo, sin ningún archivo, obtener el ícono de una extensión determinada?

Utilice el método GetFileIcon de este artículo de CodeProject de Paul Ingles y pase .ext como parámetro de name .

El método GetFileIcon es un contenedor alrededor de la SHGetFileInfo nativa y se copia aquí para ilustración:

 public static System.Drawing.Icon GetFileIcon(string name, IconSize size, bool linkOverlay) { Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO(); uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES; if (true == linkOverlay) flags += Shell32.SHGFI_LINKOVERLAY; /* Check the size specified for return. */ if (IconSize.Small == size) { flags += Shell32.SHGFI_SMALLICON ; // include the small icon flag } else { flags += Shell32.SHGFI_LARGEICON ; // include the large icon flag } Shell32.SHGetFileInfo( name, Shell32.FILE_ATTRIBUTE_NORMAL, ref shfi, (uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi), flags ); // Copy (clone) the returned icon to a new object, thus allowing us // to call DestroyIcon immediately System.Drawing.Icon icon = (System.Drawing.Icon) System.Drawing.Icon.FromHandle(shfi.hIcon).Clone(); User32.DestroyIcon( shfi.hIcon ); // Cleanup return icon; } 

El siguiente código también está basado en la solución de Paul Ingles , pero:

  • ImageSource con WPF ( ImageSource lugar de Icon )
  • Tiene un simple almacenamiento en caché
  • Se eliminó todo lo relacionado con los directorios (solo tengo archivos en mi caso)
  • Refactorizado utilizando sugerencias R # y envuelto con una API simple de una sola clase

Lo probé en Windows 7 y Windows XP SP3 , funciona como se esperaba con cualquier cadena como fileName .

 using System; using System.Collections.Generic; using System.Drawing; using System.IO; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; ///  /// Internals are mostly from here: http://www.codeproject.com/Articles/2532/Obtaining-and-managing-file-and-folder-icons-using /// Caches all results. ///  public static class IconManager { private static readonly Dictionary _smallIconCache = new Dictionary(); private static readonly Dictionary _largeIconCache = new Dictionary(); ///  /// Get an icon for a given filename ///  /// any filename /// 16x16 or 32x32 icon /// null if path is null, otherwise - an icon public static ImageSource FindIconForFilename(string fileName, bool large) { var extension = Path.GetExtension(fileName); if (extension == null) return null; var cache = large ? _largeIconCache : _smallIconCache; ImageSource icon; if (cache.TryGetValue(extension, out icon)) return icon; icon = IconReader.GetFileIcon(fileName, large ? IconReader.IconSize.Large : IconReader.IconSize.Small, false).ToImageSource(); cache.Add(extension, icon); return icon; } ///  /// http://stackoverflow.com/a/6580799/1943849 ///  static ImageSource ToImageSource(this Icon icon) { var imageSource = Imaging.CreateBitmapSourceFromHIcon( icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); return imageSource; } ///  /// Provides static methods to read system icons for both folders and files. ///  ///  /// IconReader.GetFileIcon("c:\\general.xls"); ///  static class IconReader { ///  /// Options to specify the size of icons to return. ///  public enum IconSize { ///  /// Specify large icon - 32 pixels by 32 pixels. ///  Large = 0, ///  /// Specify small icon - 16 pixels by 16 pixels. ///  Small = 1 } ///  /// Returns an icon for a given file - indicated by the name parameter. ///  /// Pathname for file. /// Large or small /// Whether to include the link icon /// System.Drawing.Icon public static Icon GetFileIcon(string name, IconSize size, bool linkOverlay) { var shfi = new Shell32.Shfileinfo(); var flags = Shell32.ShgfiIcon | Shell32.ShgfiUsefileattributes; if (linkOverlay) flags += Shell32.ShgfiLinkoverlay; /* Check the size specified for return. */ if (IconSize.Small == size) flags += Shell32.ShgfiSmallicon; else flags += Shell32.ShgfiLargeicon; Shell32.SHGetFileInfo(name, Shell32.FileAttributeNormal, ref shfi, (uint)Marshal.SizeOf(shfi), flags); // Copy (clone) the returned icon to a new object, thus allowing us to clean-up properly var icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone(); User32.DestroyIcon(shfi.hIcon); // Cleanup return icon; } } ///  /// Wraps necessary Shell32.dll structures and functions required to retrieve Icon Handles using SHGetFileInfo. Code /// courtesy of MSDN Cold Rooster Consulting case study. ///  static class Shell32 { private const int MaxPath = 256; [StructLayout(LayoutKind.Sequential)] public struct Shfileinfo { private const int Namesize = 80; public readonly IntPtr hIcon; private readonly int iIcon; private readonly uint dwAttributes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MaxPath)] private readonly string szDisplayName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Namesize)] private readonly string szTypeName; }; public const uint ShgfiIcon = 0x000000100; // get icon public const uint ShgfiLinkoverlay = 0x000008000; // put a link overlay on icon public const uint ShgfiLargeicon = 0x000000000; // get large icon public const uint ShgfiSmallicon = 0x000000001; // get small icon public const uint ShgfiUsefileattributes = 0x000000010; // use passed dwFileAttribute public const uint FileAttributeNormal = 0x00000080; [DllImport("Shell32.dll")] public static extern IntPtr SHGetFileInfo( string pszPath, uint dwFileAttributes, ref Shfileinfo psfi, uint cbFileInfo, uint uFlags ); } ///  /// Wraps necessary functions imported from User32.dll. Code courtesy of MSDN Cold Rooster Consulting example. ///  static class User32 { ///  /// Provides access to function required to delete handle. This method is used internally /// and is not required to be called separately. ///  /// Pointer to icon handle. /// N/A [DllImport("User32.dll")] public static extern int DestroyIcon(IntPtr hIcon); } } 

Se puede hacer mucho más simple:

 System.Drawing.Icon.ExtractAssociatedIcon(""); 

Nota importante: lanzará una excepción si el archivo no existe, por lo que vale la pena agregar validación.