如何在C#中获取通用文件types图标?

正如在这个问题上获得常见文件types图标 ,它是很有可能的Windows程序使用C ++ Shell API获取注册文件types的图标。 这些图标可能存在也可能不存在于磁盘上 – 例如,我们想制作自己的自定义文件浏览器,并且想要显示与文件相关的系统图标。

是否有一个本地的C#方式来获取各种文件types的图标(如果是这样,如何),或者必须通过PInvoke与shell API来完成?

作为一个后续,如果有一个本地.NET的方式,是否有一个跨平台的方式来做到这一点?

Solutions Collecting From Web of "如何在C#中获取通用文件types图标?"

看看: http : //mvolo.com/display-pretty-file-icons-in-your-aspnet-applications-with-iconhandler/

这不是最干净的解决方案,但它的工作原理。 否则,请尝试使用基于MIME类型或文件扩展名的图标库。

我的一个老的开源项目包括一个Icon类 ,它可以完全实现这个功能,随时随地都可以使用它,看到我把这个文件放在公有领域的年龄,但是大部分情况下它只是PInvoke。

要获取您使用的图标,例如:

Icon zipIcon = BlackFox.Win32.Icons.IconFromExtension(".zip", SystemIconSize.Small); 

全样本:

 using System; using System.Windows.Forms; using BlackFox.Win32; using System.Drawing; class Program { static void Main(string[] args) { PictureBox pict = new PictureBox(); pict.Image = Icons.IconFromExtension(".zip", Icons.SystemIconSize.Large).ToBitmap(); pict.Dock = DockStyle.Fill; pict.SizeMode = PictureBoxSizeMode.CenterImage; Form form = new Form(); form.Controls.Add(pict); Application.Run(form); } } 

图书馆 :

 using System; using System.Drawing; using System.Runtime.InteropServices; using Microsoft.Win32; using System.Reflection; using System.Collections.Generic; namespace BlackFox.Win32 { public static class Icons { #region Custom exceptions class public class IconNotFoundException : Exception { public IconNotFoundException(string fileName, int index) : base(string.Format("Icon with Id = {0} wasn't found in file {1}", index, fileName)) { } } public class UnableToExtractIconsException : Exception { public UnableToExtractIconsException(string fileName, int firstIconIndex, int iconCount) : base(string.Format("Tryed to extract {2} icons starting from the one with id {1} from the \"{0}\" file but failed", fileName, firstIconIndex, iconCount)) { } } #endregion #region DllImports /// <summary> /// Contains information about a file object. /// </summary> struct SHFILEINFO { /// <summary> /// Handle to the icon that represents the file. You are responsible for /// destroying this handle with DestroyIcon when you no longer need it. /// </summary> public IntPtr hIcon; /// <summary> /// Index of the icon image within the system image list. /// </summary> public IntPtr iIcon; /// <summary> /// Array of values that indicates the attributes of the file object. /// For information about these values, see the IShellFolder::GetAttributesOf /// method. /// </summary> public uint dwAttributes; /// <summary> /// String that contains the name of the file as it appears in the Microsoft /// Windows Shell, or the path and file name of the file that contains the /// icon representing the file. /// </summary> [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szDisplayName; /// <summary> /// String that describes the type of file. /// </summary> [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)] public string szTypeName; }; [Flags] enum FileInfoFlags : int { /// <summary> /// Retrieve the handle to the icon that represents the file and the index /// of the icon within the system image list. The handle is copied to the /// hIcon member of the structure specified by psfi, and the index is copied /// to the iIcon member. /// </summary> SHGFI_ICON = 0x000000100, /// <summary> /// Indicates that the function should not attempt to access the file /// specified by pszPath. Rather, it should act as if the file specified by /// pszPath exists with the file attributes passed in dwFileAttributes. /// </summary> SHGFI_USEFILEATTRIBUTES = 0x000000010 } /// <summary> /// Creates an array of handles to large or small icons extracted from /// the specified executable file, dynamic-link library (DLL), or icon /// file. /// </summary> /// <param name="lpszFile"> /// Name of an executable file, DLL, or icon file from which icons will /// be extracted. /// </param> /// <param name="nIconIndex"> /// <para> /// Specifies the zero-based index of the first icon to extract. For /// example, if this value is zero, the function extracts the first /// icon in the specified file. /// </para> /// <para> /// If this value is  1 and <paramref name="phiconLarge"/> and /// <paramref name="phiconSmall"/> are both NULL, the function returns /// the total number of icons in the specified file. If the file is an /// executable file or DLL, the return value is the number of /// RT_GROUP_ICON resources. If the file is an .ico file, the return /// value is 1. /// </para> /// <para> /// Windows 95/98/Me, Windows NT 4.0 and later: If this value is a /// negative number and either <paramref name="phiconLarge"/> or /// <paramref name="phiconSmall"/> is not NULL, the function begins by /// extracting the icon whose resource identifier is equal to the /// absolute value of <paramref name="nIconIndex"/>. For example, use -3 /// to extract the icon whose resource identifier is 3. /// </para> /// </param> /// <param name="phIconLarge"> /// An array of icon handles that receives handles to the large icons /// extracted from the file. If this parameter is NULL, no large icons /// are extracted from the file. /// </param> /// <param name="phIconSmall"> /// An array of icon handles that receives handles to the small icons /// extracted from the file. If this parameter is NULL, no small icons /// are extracted from the file. /// </param> /// <param name="nIcons"> /// Specifies the number of icons to extract from the file. /// </param> /// <returns> /// If the <paramref name="nIconIndex"/> parameter is -1, the /// <paramref name="phIconLarge"/> parameter is NULL, and the /// <paramref name="phiconSmall"/> parameter is NULL, then the return /// value is the number of icons contained in the specified file. /// Otherwise, the return value is the number of icons successfully /// extracted from the file. /// </returns> [DllImport("Shell32", CharSet = CharSet.Auto)] extern static int ExtractIconEx( [MarshalAs(UnmanagedType.LPTStr)] string lpszFile, int nIconIndex, IntPtr[] phIconLarge, IntPtr[] phIconSmall, int nIcons); [DllImport("Shell32", CharSet = CharSet.Auto)] extern static IntPtr SHGetFileInfo( string pszPath, int dwFileAttributes, out SHFILEINFO psfi, int cbFileInfo, FileInfoFlags uFlags); #endregion /// <summary> /// Two constants extracted from the FileInfoFlags, the only that are /// meaningfull for the user of this class. /// </summary> public enum SystemIconSize : int { Large = 0x000000000, Small = 0x000000001 } /// <summary> /// Get the number of icons in the specified file. /// </summary> /// <param name="fileName">Full path of the file to look for.</param> /// <returns></returns> static int GetIconsCountInFile(string fileName) { return ExtractIconEx(fileName, -1, null, null, 0); } #region ExtractIcon-like functions public static void ExtractEx(string fileName, List<Icon> largeIcons, List<Icon> smallIcons, int firstIconIndex, int iconCount) { /* * Memory allocations */ IntPtr[] smallIconsPtrs = null; IntPtr[] largeIconsPtrs = null; if (smallIcons != null) { smallIconsPtrs = new IntPtr[iconCount]; } if (largeIcons != null) { largeIconsPtrs = new IntPtr[iconCount]; } /* * Call to native Win32 API */ int apiResult = ExtractIconEx(fileName, firstIconIndex, largeIconsPtrs, smallIconsPtrs, iconCount); if (apiResult != iconCount) { throw new UnableToExtractIconsException(fileName, firstIconIndex, iconCount); } /* * Fill lists */ if (smallIcons != null) { smallIcons.Clear(); foreach (IntPtr actualIconPtr in smallIconsPtrs) { smallIcons.Add(Icon.FromHandle(actualIconPtr)); } } if (largeIcons != null) { largeIcons.Clear(); foreach (IntPtr actualIconPtr in largeIconsPtrs) { largeIcons.Add(Icon.FromHandle(actualIconPtr)); } } } public static List<Icon> ExtractEx(string fileName, SystemIconSize size, int firstIconIndex, int iconCount) { List<Icon> iconList = new List<Icon>(); switch (size) { case SystemIconSize.Large: ExtractEx(fileName, iconList, null, firstIconIndex, iconCount); break; case SystemIconSize.Small: ExtractEx(fileName, null, iconList, firstIconIndex, iconCount); break; default: throw new ArgumentOutOfRangeException("size"); } return iconList; } public static void Extract(string fileName, List<Icon> largeIcons, List<Icon> smallIcons) { int iconCount = GetIconsCountInFile(fileName); ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount); } public static List<Icon> Extract(string fileName, SystemIconSize size) { int iconCount = GetIconsCountInFile(fileName); return ExtractEx(fileName, size, 0, iconCount); } public static Icon ExtractOne(string fileName, int index, SystemIconSize size) { try { List<Icon> iconList = ExtractEx(fileName, size, index, 1); return iconList[0]; } catch (UnableToExtractIconsException) { throw new IconNotFoundException(fileName, index); } } public static void ExtractOne(string fileName, int index, out Icon largeIcon, out Icon smallIcon) { List<Icon> smallIconList = new List<Icon>(); List<Icon> largeIconList = new List<Icon>(); try { ExtractEx(fileName, largeIconList, smallIconList, index, 1); largeIcon = largeIconList[0]; smallIcon = smallIconList[0]; } catch (UnableToExtractIconsException) { throw new IconNotFoundException(fileName, index); } } #endregion //this will look throw the registry //to find if the Extension have an icon. public static Icon IconFromExtension(string extension, SystemIconSize size) { // Add the '.' to the extension if needed if (extension[0] != '.') extension = '.' + extension; //opens the registry for the wanted key. RegistryKey Root = Registry.ClassesRoot; RegistryKey ExtensionKey = Root.OpenSubKey(extension); ExtensionKey.GetValueNames(); RegistryKey ApplicationKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString()); //gets the name of the file that have the icon. string IconLocation = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString(); string[] IconPath = IconLocation.Split(','); if (IconPath[1] == null) IconPath[1] = "0"; IntPtr[] Large = new IntPtr[1], Small = new IntPtr[1]; //extracts the icon from the file. ExtractIconEx(IconPath[0], Convert.ToInt16(IconPath[1]), Large, Small, 1); return size == SystemIconSize.Large ? Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]); } public static Icon IconFromExtensionShell(string extension, SystemIconSize size) { //add '.' if nessesry if (extension[0] != '.') extension = '.' + extension; //temp struct for getting file shell info SHFILEINFO fileInfo = new SHFILEINFO(); SHGetFileInfo( extension, 0, out fileInfo, Marshal.SizeOf(fileInfo), FileInfoFlags.SHGFI_ICON | FileInfoFlags.SHGFI_USEFILEATTRIBUTES | (FileInfoFlags)size); return Icon.FromHandle(fileInfo.hIcon); } public static Icon IconFromResource(string resourceName) { Assembly assembly = Assembly.GetCallingAssembly(); return new Icon(assembly.GetManifestResourceStream(resourceName)); } /// <summary> /// Parse strings in registry who contains the name of the icon and /// the index of the icon an return both parts. /// </summary> /// <param name="regString">The full string in the form "path,index" as found in registry.</param> /// <param name="fileName">The "path" part of the string.</param> /// <param name="index">The "index" part of the string.</param> public static void ExtractInformationsFromRegistryString( string regString, out string fileName, out int index) { if (regString == null) { throw new ArgumentNullException("regString"); } if (regString.Length == 0) { throw new ArgumentException("The string should not be empty.", "regString"); } index = 0; string[] strArr = regString.Replace("\"", "").Split(','); fileName = strArr[0].Trim(); if (strArr.Length > 1) { int.TryParse(strArr[1].Trim(), out index); } } public static Icon ExtractFromRegistryString(string regString, SystemIconSize size) { string fileName; int index; ExtractInformationsFromRegistryString(regString, out fileName, out index); return ExtractOne(fileName, index, size); } } } 

我相信你已经找到了解决问题的办法,但为了别人的利益,我对VirtualBlackFox的解决方案做了一些修改。

只要替换IconFromExtension方法…

 public static Icon IconFromExtension(string extension, SystemIconSize size) { // Add the '.' to the extension if needed if (extension[0] != '.') extension = '.' + extension; //opens the registry for the wanted key. RegistryKey Root = Registry.ClassesRoot; RegistryKey ExtensionKey = Root.OpenSubKey(extension); ExtensionKey.GetValueNames(); RegistryKey ApplicationKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString()); RegistryKey CurrentVer = null; try { CurrentVer = Root.OpenSubKey(ApplicationKey.OpenSubKey("CurVer").GetValue("").ToString()); } catch (Exception ex) { //current version not found... carry on without it? } if (CurrentVer != null) ApplicationKey = CurrentVer; //gets the name of the file that have the icon. string IconLocation = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString(); string[] IconPath = IconLocation.Split(','); IntPtr[] Large = null; IntPtr[] Small = null; int iIconPathNumber = 0; if (IconPath.Length > 1) iIconPathNumber = 1; else iIconPathNumber = 0; if (IconPath[iIconPathNumber] == null) IconPath[iIconPathNumber] = "0"; Large = new IntPtr[1]; Small = new IntPtr[1]; //extracts the icon from the file. if (iIconPathNumber > 0) { ExtractIconEx(IconPath[0], Convert.ToInt16(IconPath[iIconPathNumber]), Large, Small, 1); } else { ExtractIconEx(IconPath[0], Convert.ToInt16(0), Large, Small, 1); } return size == SystemIconSize.Large ? Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]); } 

Icon.ExtractAssociatedIcon()不会做的伎俩。 正如MSDN所说,它只提取文件中包含的图标。 所以创建虚拟文件也无济于事。 据我所知,你必须去p / invoke的方式来获得这些图标。 与此有关的一个问题是这个 。 MaLio似乎有一个相当完整的例子,如何使用p / invoke获取图标。

我不知道一个平台不可知的方式来做到这一点(我不认为有一个)。

抱歉,我无法为您提供更好的消息!

这个班应该做这个工作。 传递文件名(带路径)或文件夹名称(带路径)。

 public static class FileIcon { [DllImport("shell32.dll")] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); [StructLayout(LayoutKind.Sequential)] private 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; }; private const uint SHGFI_ICON = 0x100; private const uint SHGFI_LARGEICON = 0x0; // 'Large icon private const uint SHGFI_SMALLICON = 0x1; // 'Small icon public static System.Drawing.Icon GetLargeIcon(string file) { FileIcon.SHFILEINFO shinfo = new FileIcon.SHFILEINFO(); IntPtr hImgLarge = FileIcon.SHGetFileInfo(file, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), FileIcon.SHGFI_ICON | FileIcon.SHGFI_LARGEICON); return System.Drawing.Icon.FromHandle(shinfo.hIcon); } public static System.Drawing.Icon GetSmallIcon(string file) { FileIcon.SHFILEINFO shinfo = new FileIcon.SHFILEINFO(); IntPtr hImgLarge = FileIcon.SHGetFileInfo(file, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), FileIcon.SHGFI_ICON | FileIcon.SHGFI_SMALLICON); return System.Drawing.Icon.FromHandle(shinfo.hIcon); } } 

可以使用IQueryAssociations接口来代替浏览注册表。 这个接口也可以用来获得更多关于注册文件类型的信息(参见ie ASSOCSTR类型)。 下面我附上代码,它取代了VirtualBlackFox解决方案中的IconFromExtension方法(部分代码保持不变):

 public static Icon IconFromExtension(string extension, SystemIconSize size) { if (extension[0] != '.') extension = '.' + extension; object obj; shell.AssocCreate(shell.CLSID_QueryAssociations, ref shell.IID_IQueryAssociations, out obj); var qa = (shell.IQueryAssociations)obj; qa.Init(shell.ASSOCF.INIT_DEFAULTTOSTAR, Convert.ToString(extension), UIntPtr.Zero, IntPtr.Zero); var bufSize = 0; qa.GetString(shell.ASSOCF.NOTRUNCATE, shell.ASSOCSTR.DEFAULTICON, null, null, ref bufSize); var sb = new StringBuilder(bufSize); qa.GetString(shell.ASSOCF.NOTRUNCATE, shell.ASSOCSTR.DEFAULTICON, null, sb, ref bufSize); if (!String.IsNullOrEmpty(sb.ToString())) { var iconLocation = sb.ToString(); var iconPath = iconLocation.Split(','); var iIconPathNumber = iconPath.Length > 1 ? 1 : 0; if (iconPath[iIconPathNumber] == null) iconPath[iIconPathNumber] = "0"; var large = new IntPtr[1]; var small = new IntPtr[1]; //extracts the icon from the file. ExtractIconEx(iconPath[0], iIconPathNumber > 0 ? Convert.ToInt16(iconPath[iIconPathNumber]) : Convert.ToInt16(0), large, small, 1); return size == SystemIconSize.Large ? Icon.FromHandle(large[0]) : Icon.FromHandle(small[0]); } return IntPtr.Zero; } 

除了上面的代码外,还需要一个“shell”类 – Shell API的一个包装器(下面仅限于AssocCreate和必要的类型):

 using System; using System.Runtime.InteropServices; using System.Text; #pragma warning disable 1591 // ReSharper disable InconsistentNaming namespace <put_your_appropriate_namespace_here> { public class shell { [DllImport("shlwapi.dll")] public extern static int AssocCreate( Guid clsid, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppv); [Flags] public enum ASSOCF { INIT_NOREMAPCLSID = 0x00000001, INIT_BYEXENAME = 0x00000002, OPEN_BYEXENAME = 0x00000002, INIT_DEFAULTTOSTAR = 0x00000004, INIT_DEFAULTTOFOLDER = 0x00000008, NOUSERSETTINGS = 0x00000010, NOTRUNCATE = 0x00000020, VERIFY = 0x00000040, REMAPRUNDLL = 0x00000080, NOFIXUPS = 0x00000100, IGNOREBASECLASS = 0x00000200, INIT_IGNOREUNKNOWN = 0x00000400 } public enum ASSOCSTR { COMMAND = 1, EXECUTABLE, FRIENDLYDOCNAME, FRIENDLYAPPNAME, NOOPEN, SHELLNEWVALUE, DDECOMMAND, DDEIFEXEC, DDEAPPLICATION, DDETOPIC, INFOTIP, QUICKTIP, TILEINFO, CONTENTTYPE, DEFAULTICON, SHELLEXTENSION } public enum ASSOCKEY { SHELLEXECCLASS = 1, APP, CLASS, BASECLASS } public enum ASSOCDATA { MSIDESCRIPTOR = 1, NOACTIVATEHANDLER, QUERYCLASSSTORE, HASPERUSERASSOC, EDITFLAGS, VALUE } [Guid("c46ca590-3c3f-11d2-bee6-0000f805ca57"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IQueryAssociations { void Init( [In] ASSOCF flags, [In, MarshalAs(UnmanagedType.LPWStr)] string pszAssoc, [In] UIntPtr hkProgid, [In] IntPtr hwnd); void GetString( [In] ASSOCF flags, [In] ASSOCSTR str, [In, MarshalAs(UnmanagedType.LPWStr)] string pwszExtra, [Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pwszOut, [In, Out] ref int pcchOut); void GetKey( [In] ASSOCF flags, [In] ASSOCKEY str, [In, MarshalAs(UnmanagedType.LPWStr)] string pwszExtra, [Out] out UIntPtr phkeyOut); void GetData( [In] ASSOCF flags, [In] ASSOCDATA data, [In, MarshalAs(UnmanagedType.LPWStr)] string pwszExtra, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 4)] out byte[] pvOut, [In, Out] ref int pcbOut); void GetEnum(); // not used actually } public static Guid CLSID_QueryAssociations = new Guid("a07034fd-6caa-4954-ac3f-97a27216f98a"); public static Guid IID_IQueryAssociations = new Guid("c46ca590-3c3f-11d2-bee6-0000f805ca57"); } } 

对于需要ImageSource的WPF用户:

将图标的返回类型替换为ImageSource,将return子句替换为:

  var iconPtr = size == SystemIconSize.Large ? large[0] : small[0]; if (iconPtr != IntPtr.Zero) { return Imaging.CreateBitmapSourceFromHIcon( iconPtr, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); }