C# 获取exe、dll中的图标,支持获取256x256分辨率

在网上找过许多文章,都没有成功获取过大图标,只能获取最大32x32。最后自己尝试了相关的windows api,终于找到一个可用的。

 

主要用到的C++的PrivateExtractIcons函数,具体说明请看:PrivateExtractIcons function

该函数原文有个说明可能需要注意一下:[This function is not intended for general use. It may be altered or unavailable in subsequent versions of Windows.]

 

 1 UINT WINAPI PrivateExtractIcons(
 2   _In_      LPCTSTR lpszFile,
 3   _In_      int     nIconIndex,
 4   _In_      int     cxIcon,
 5   _In_      int     cyIcon,
 6   _Out_opt_ HICON   *phicon,
 7   _Out_opt_ UINT    *piconid,
 8   _In_      UINT    nIcons,
 9   _In_      UINT    flags
10 );

C#使用DLL import进行引用。

 1 [DllImport("User32.dll")]
 2 public static extern int PrivateExtractIcons(
 3     string lpszFile, //文件名可以是exe,dll,ico,cur,ani,bmp
 4     int nIconIndex,  //从第几个图标开始获取
 5     int cxIcon,      //获取图标的尺寸x
 6     int cyIcon,      //获取图标的尺寸y
 7     IntPtr[] phicon, //获取到的图标指针数组
 8     int[] piconid,   //图标对应的资源编号
 9     int nIcons,      //指定获取的图标数量,仅当文件类型为.exe 和 .dll时候可用
10     int flags        //标志,默认0就可以,具体可以看LoadImage函数
11 );

 

说明:如果想要获取的图标尺寸为256x256,而实际资源文件中的图标尺寸小于256x256的话,则会获取存在的最高分标率,色彩数最丰富的的图标,并拉伸。

 

具体代码如下

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Drawing;
 4 using System.Drawing.Imaging;
 5 using System.IO;
 6 using System.Linq;
 7 using System.Runtime.InteropServices;
 8 using System.Text;
 9 using System.Threading.Tasks;
10 
11 namespace TryGetExeLargeIcon
12 {
13     class Program
14     {
15         [STAThread]
16         static void Main(string[] args)
17         {
18             //选择文件对话框
19             var opfd = new System.Windows.Forms.OpenFileDialog { Filter = "资源文件|*.exe;*.dll" };
20             if (opfd.ShowDialog() != System.Windows.Forms.DialogResult.OK) return;
21             var file = opfd.FileName;
22 
23             //指定存放图标的文件夹
24             const string folderToSave = "D:\\temp\\";
25             if (!Directory.Exists(folderToSave)) Directory.CreateDirectory(folderToSave);
26 
27             //选中文件中的图标总数
28             var iconTotalCount = PrivateExtractIcons(file, 0, 0, 0, null, null, 0, 0);
29 
30             //用于接收获取到的图标指针
31             IntPtr[] hIcons = new IntPtr[iconTotalCount];
32             //对应的图标id
33             int[] ids = new int[iconTotalCount];
34             //成功获取到的图标个数
35             var successCount = PrivateExtractIcons(file, 0, 256, 256, hIcons, ids, iconTotalCount, 0);
36 
37             //遍历并保存图标
38             for (var i = 0; i < successCount; i++)
39             {
40                 //指针为空,跳过
41                 if (hIcons[i] == IntPtr.Zero) continue;
42 
43                 using (var ico = Icon.FromHandle(hIcons[i]))
44                 {
45                     using (var myIcon = ico.ToBitmap())
46                     {
47                         myIcon.Save(folderToSave + ids[i].ToString("000") + ".png", ImageFormat.Png);
48                     }
49                 }
50                 //内存回收
51                 DestroyIcon(hIcons[i]);
52             }
53         }
54 
55 
56         //details: https://msdn.microsoft.com/en-us/library/windows/desktop/ms648075(v=vs.85).aspx
57         //Creates an array of handles to icons that are extracted from a specified file.
58         //This function extracts from executable (.exe), DLL (.dll), icon (.ico), cursor (.cur), animated cursor (.ani), and bitmap (.bmp) files. 
59         //Extractions from Windows 3.x 16-bit executables (.exe or .dll) are also supported.
60         [DllImport("User32.dll")]
61         public static extern int PrivateExtractIcons(
62             string lpszFile, //file name
63             int nIconIndex,  //The zero-based index of the first icon to extract.
64             int cxIcon,      //The horizontal icon size wanted.
65             int cyIcon,      //The vertical icon size wanted.
66             IntPtr[] phicon, //(out) A pointer to the returned array of icon handles.
67             int[] piconid,   //(out) A pointer to a returned resource identifier.
68             int nIcons,      //The number of icons to extract from the file. Only valid when *.exe and *.dll
69             int flags        //Specifies flags that control this function.
70         );
71 
72         //details:https://msdn.microsoft.com/en-us/library/windows/desktop/ms648063(v=vs.85).aspx
73         //Destroys an icon and frees any memory the icon occupied.
74         [DllImport("User32.dll")]
75         public static extern bool DestroyIcon(
76             IntPtr hIcon //A handle to the icon to be destroyed. The icon must not be in use.
77         );
78     }
79 }

 

posted on 2017-09-13 16:57  jmlsaul  阅读(3043)  评论(0编辑  收藏  举报