using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Runtime.InteropServices; namespace Crysome.Client.Util; internal static class ShellSmallIconPng { private 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; } private const uint SHGFI_ICON = 256u; private const uint SHGFI_SMALLICON = 1u; private const uint SHGFI_USEFILEATTRIBUTES = 16u; private const uint FILE_ATTRIBUTE_DIRECTORY = 16u; [DllImport("shell32.dll", CharSet = CharSet.Auto)] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbFileInfo, uint uFlags); [DllImport("user32.dll", CharSet = CharSet.Auto)] private static extern bool DestroyIcon(IntPtr hIcon); public static byte[] TryGetPng(string fullPath, bool isDirectory) { if (string.IsNullOrEmpty(fullPath)) { return null; } try { if (!isDirectory && File.Exists(fullPath)) { using (Icon icon = Icon.ExtractAssociatedIcon(fullPath)) { if (icon == null) { return null; } return IconToPng(icon); } } SHFILEINFO psfi = default(SHFILEINFO); uint dwFileAttributes = (isDirectory ? 16u : 0u); if (SHGetFileInfo(fullPath, dwFileAttributes, ref psfi, (uint)Marshal.SizeOf(), 273u) == IntPtr.Zero || psfi.hIcon == IntPtr.Zero) { return null; } IntPtr hIcon = psfi.hIcon; try { using Icon icon2 = Icon.FromHandle(hIcon); using Icon ico = (Icon)icon2.Clone(); return IconToPng(ico); } finally { DestroyIcon(hIcon); } } catch { return null; } } private static byte[] IconToPng(Icon ico) { using Bitmap bitmap = ico.ToBitmap(); using MemoryStream memoryStream = new MemoryStream(); bitmap.Save(memoryStream, ImageFormat.Png); return memoryStream.ToArray(); } }