using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; using Microsoft.Win32; namespace prBrowser { public static class FileIconUtils { public class IconNotFoundException : Exception { public IconNotFoundException(string fileName, int index) : base($"Icon with Id = {index} wasn't found in file {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)) { } } 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; } [Flags] private enum FileInfoFlags { SHGFI_ICON = 0x100, SHGFI_USEFILEATTRIBUTES = 0x10 } public static MemoryStream GetFileIcon(string name, FileIconSize size) { Icon icon = IconFromExtension(name.GetAfter("."), size); using (icon) { using Bitmap bmp = icon.ToBitmap(); MemoryStream ms = new MemoryStream(); bmp.Save(ms, ImageFormat.Png); ms.Seek(0L, SeekOrigin.Begin); return ms; } } [DllImport("Shell32", CharSet = CharSet.Auto)] private static extern int ExtractIconEx([MarshalAs(UnmanagedType.LPTStr)] string lpszFile, int nIconIndex, IntPtr[] phIconLarge, IntPtr[] phIconSmall, int nIcons); [DllImport("Shell32", CharSet = CharSet.Auto)] private static extern IntPtr SHGetFileInfo(string pszPath, int dwFileAttributes, out SHFILEINFO psfi, int cbFileInfo, FileInfoFlags uFlags); public static void ExtractEx(string fileName, List largeIcons, List smallIcons, int firstIconIndex, int iconCount) { IntPtr[] smallIconsPtrs = null; IntPtr[] largeIconsPtrs = null; if (smallIcons != null) { smallIconsPtrs = new IntPtr[iconCount]; } if (largeIcons != null) { largeIconsPtrs = new IntPtr[iconCount]; } int apiResult = ExtractIconEx(fileName, firstIconIndex, largeIconsPtrs, smallIconsPtrs, iconCount); if (apiResult != iconCount) { throw new UnableToExtractIconsException(fileName, firstIconIndex, iconCount); } if (smallIcons != null) { smallIcons.Clear(); IntPtr[] array = smallIconsPtrs; foreach (IntPtr actualIconPtr2 in array) { smallIcons.Add(Icon.FromHandle(actualIconPtr2)); } } if (largeIcons != null) { largeIcons.Clear(); IntPtr[] array2 = largeIconsPtrs; foreach (IntPtr actualIconPtr in array2) { largeIcons.Add(Icon.FromHandle(actualIconPtr)); } } } public static List ExtractEx(string fileName, FileIconSize size, int firstIconIndex, int iconCount) { List iconList = new List(); switch (size) { case FileIconSize.Large: ExtractEx(fileName, iconList, null, firstIconIndex, iconCount); break; case FileIconSize.Small: ExtractEx(fileName, null, iconList, firstIconIndex, iconCount); break; default: throw new ArgumentOutOfRangeException("size"); } return iconList; } public static void Extract(string fileName, List largeIcons, List smallIcons) { int iconCount = GetIconsCountInFile(fileName); ExtractEx(fileName, largeIcons, smallIcons, 0, iconCount); } public static List Extract(string fileName, FileIconSize size) { int iconCount = GetIconsCountInFile(fileName); return ExtractEx(fileName, size, 0, iconCount); } public static Icon ExtractOne(string fileName, int index, FileIconSize size) { try { List 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 smallIconList = new List(); List largeIconList = new List(); try { ExtractEx(fileName, largeIconList, smallIconList, index, 1); largeIcon = largeIconList[0]; smallIcon = smallIconList[0]; } catch (UnableToExtractIconsException) { throw new IconNotFoundException(fileName, index); } } private static int GetIconsCountInFile(string fileName) { return ExtractIconEx(fileName, -1, null, null, 0); } public static Icon IconFromExtension(string extension, FileIconSize size) { if (extension[0] != '.') { extension = "." + extension; } extension = extension.ToLower(); RegistryKey Root = Registry.ClassesRoot; RegistryKey ExtensionKey = Root.OpenSubKey(extension); ExtensionKey.GetValueNames(); RegistryKey ApplicationKey = Root.OpenSubKey(ExtensionKey.GetValue("").ToString()); string IconLocation = ApplicationKey.OpenSubKey("DefaultIcon").GetValue("").ToString(); string[] IconPath = IconLocation.Split(','); IntPtr[] Large = null; IntPtr[] Small = null; int iIconPathNumber = 0; iIconPathNumber = ((IconPath.Length > 1) ? 1 : 0); if (IconPath[iIconPathNumber] == null) { IconPath[iIconPathNumber] = "0"; } Large = new IntPtr[1]; Small = new IntPtr[1]; 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 == FileIconSize.Large) ? Icon.FromHandle(Large[0]) : Icon.FromHandle(Small[0]); } 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("不可为空字符串.", "regString"); } index = 0; string[] strArr = regString.Replace("\"", "").Split(','); fileName = strArr[0].Trim(); if (strArr.Length > 1) { int.TryParse(strArr[1].Trim(), out index); } } } }