如何提取Windows 11中文件类型的24x24等多尺寸原生图标?
提取Windows 11中文件扩展名的原生16/24/32/48/64x64图标(无需实际文件)
在Windows 11 + .NET Framework 4.8环境下,要绕过系统图像列表的尺寸限制、直接提取文件扩展名的全尺寸原生图标,可通过以下方案实现,避免缩放导致的模糊问题:
核心思路
- 用
SHGetFileInfo结合特定标志,仅通过扩展名获取关联图标所在的DLL/EXE路径及索引(无需实际文件存在)。 - 调用
SHDefExtractIcon从图标资源中直接提取目标尺寸的原生图标——Windows 11的标准文件类型图标库已内置16/24/32/48/64x64这些尺寸,无需手动缩放。
具体实现(C#)
先定义所需的Win32 P/Invoke接口:
using System; using System.Drawing; using System.Runtime.InteropServices; public static class FileIconExtractor { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 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; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] public string szIconPath; } [DllImport("shell32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags); [DllImport("shell32.dll", CharSet = CharSet.Unicode)] private static extern int SHDefExtractIcon(string pszIconPath, int iIconIndex, uint uFlags, out IntPtr phiconLarge, out IntPtr phiconSmall, uint nIconSize); private const uint SHGFI_ICONLOCATION = 0x000001000; private const uint SHGFI_USEFILEATTRIBUTES = 0x000000010; private const uint FILE_ATTRIBUTE_NORMAL = 0x00000080; public static Icon ExtractNativeIcon(string extension, int size) { if (!extension.StartsWith(".")) extension = "." + extension; SHFILEINFO shfi = new SHFILEINFO(); IntPtr result = SHGetFileInfo( extension, FILE_ATTRIBUTE_NORMAL, ref shfi, (uint)Marshal.SizeOf(shfi), SHGFI_ICONLOCATION | SHGFI_USEFILEATTRIBUTES ); if (result == IntPtr.Zero || string.IsNullOrEmpty(shfi.szIconPath)) throw new InvalidOperationException("无法获取文件类型的关联图标信息"); IntPtr hIcon = IntPtr.Zero; int ret = SHDefExtractIcon( shfi.szIconPath, shfi.iIcon, 0, out hIcon, out _, (uint)size ); if (ret != 0 || hIcon == IntPtr.Zero) throw new InvalidOperationException($"无法提取{size}x{size}尺寸的图标"); try { return Icon.FromHandle(hIcon); } finally { // Icon.FromHandle会接管句柄,Dispose Icon时自动释放,无需手动操作 } } }
使用示例
// 提取PDF的24x24原生图标 Icon pdf24Icon = FileIconExtractor.ExtractNativeIcon("pdf", 24); // 提取DOCX的64x64原生图标 Icon docx64Icon = FileIconExtractor.ExtractNativeIcon("docx", 64); // 使用完毕后释放资源 pdf24Icon.Dispose(); docx64Icon.Dispose();
关键细节说明
SHGFI_ICONLOCATION标志会让SHGetFileInfo把图标所在文件路径写入szIconPath,索引写入iIcon,这是获取原生图标资源的核心。SHDefExtractIcon的nIconSize参数直接传入目标尺寸,函数会自动匹配图标资源中的原生尺寸,返回无模糊的清晰图标。SHGFI_USEFILEATTRIBUTES标志确保无需实际文件,仅通过扩展名即可获取关联信息。
内容的提问来源于stack exchange,提问作者Faraz Azhar
相关产品推荐
相关产品推荐

