通过 ExtractIconEx 读取文件图标

9268 2026-07-06 20:14:10

参考(https://blog.csdn.net/bruce135lee/article/details/79790104),使用 ExtractIconEx 获取文件/扩展名图标,在实际使用过程中,会出现读取图标卡死情况;

经测试发现在文件少的目录不会出现卡死,但是在读取 c:\windows\system32 时,会出现卡死;

翻了MSDN,有提示需要通过 DestroyIcon 释放资源。

相对于参考资料,作以下修改:

1、添加参数:tcType 用于指定需要获取的是文件还是目录;(之前通过文件扩展名的方式获取有点问题,如果文件本身没扩展名的,会误认为是目录)

2、ExtractIconEx 声明中句柄列表使用 IntPtr 类型,方便后续判断;

3、获取图标资源之后,调用 DestroyIcon 释放资源;

4、读取注册表信息时,键值的数据中文件名部分可能会使用引号(如:"\"C:\Program Files\7-Zip\7z.rar\",1")而导致获取图片失败;因此:转为字符串数组后,去掉前后空格

5、直接读取文件中的图标,限定仅 .EXE和.ICO 才读取文件自带图标;原因:有些DLL中也带有图标资源,会导致DLL文件也提取到了自带图标

最终代码:

1 ///

2 /// 通过文件名称获取文件图标

3 ///

4 /// 指定参数tcFullName的类型: FILE/DIR

5 /// 需要获取图片的全路径文件名

6 /// 是否获取大图标(32*32)

7 ///

8 private Icon GetIconByFileName(string tcType, string tcFullName, bool tlIsLarge = false)

9 {

10 Icon ico = null;

11

12 string fileType = tcFullName.Contains(".") ? tcFullName.Substring(tcFullName.LastIndexOf('.')).ToLower() : string.Empty;

13

14 RegistryKey regVersion = null;

15 string regFileType = null;

16 string regIconString = null;

17 string systemDirectory = Environment.SystemDirectory + "\\";

18 IntPtr[] phiconLarge = new IntPtr[1];

19 IntPtr[] phiconSmall = new IntPtr[1];

20 IntPtr hIcon = IntPtr.Zero;

21 uint rst = 0;

22

23 if (tcType == "FILE")

24 {

25 //含图标的文件,优先使用文件中自带图标

26 if (".exe.ico".Contains(fileType))

27 {

28 //文件名 图标索引

29 phiconLarge[0] = phiconSmall[0] = IntPtr.Zero;

30 rst = ExtractIconEx(tcFullName, 0, phiconLarge, phiconSmall, 1);

31 hIcon = tlIsLarge ? phiconLarge[0] : phiconSmall[0];

32 ico = hIcon == IntPtr.Zero ? null : Icon.FromHandle(hIcon).Clone() as Icon;

33 if (phiconLarge[0] != IntPtr.Zero) DestroyIcon(phiconLarge[0]);

34 if (phiconSmall[0] != IntPtr.Zero) DestroyIcon(phiconSmall[0]);

35 if (ico != null)

36 {

37 return ico;

38 }

39 }

40

41 //通过文件扩展名读取图标

42 regVersion = Registry.ClassesRoot.OpenSubKey(fileType, false);

43 if (regVersion != null)

44 {

45 regFileType = regVersion.GetValue("") as string;

46 regVersion.Close();

47 regVersion = Registry.ClassesRoot.OpenSubKey(regFileType + @"\DefaultIcon", false);

48 if (regVersion != null)

49 {

50 regIconString = regVersion.GetValue("") as string;

51 regVersion.Close();

52 }

53 }

54 if (regIconString == null)

55 {

56 //没有读取到文件类型注册信息,指定为未知文件类型的图标

57 regIconString = systemDirectory + "shell32.dll,0";

58 }

59 }

60 else

61 {

62 //直接指定为文件夹图标

63 regIconString = systemDirectory + "shell32.dll,3";

64 }

65

66 string[] fileIcon = regIconString.Split(new char[] { ',' });

67 //系统注册表中注册的标图不能直接提取,则返回可执行文件的通用图标

68 fileIcon = fileIcon.Length == 2 ? fileIcon : new string[] { systemDirectory + "shell32.dll", "2" };

69

70 phiconLarge[0] = phiconSmall[0] = IntPtr.Zero;

71 rst = ExtractIconEx(fileIcon[0].Trim('\"'), Int32.Parse(fileIcon[1]), phiconLarge, phiconSmall, 1);

72 hIcon = tlIsLarge ? phiconLarge[0] : phiconSmall[0];

73 ico = hIcon == IntPtr.Zero ? null : Icon.FromHandle(hIcon).Clone() as Icon;

74 if (phiconLarge[0] != IntPtr.Zero) DestroyIcon(phiconLarge[0]);

75 if (phiconSmall[0] != IntPtr.Zero) DestroyIcon(phiconSmall[0]);

76 if (ico != null)

77 {

78 return ico;

79 }

80

81 // 对于文件,如果提取文件图标失败,则重新使用可执行文件通用图标

82 if (tcType == "FILE")

83 {

84 //系统注册表中注册的标图不能直接提取,则返回可执行文件的通用图标

85 fileIcon = new string[] { systemDirectory + "shell32.dll", "2" };

86 phiconLarge = new IntPtr[1];

87 phiconSmall = new IntPtr[1];

88 rst = ExtractIconEx(fileIcon[0], Int32.Parse(fileIcon[1]), phiconLarge, phiconSmall, 1);

89 hIcon = tlIsLarge ? phiconLarge[0] : phiconSmall[0];

90 ico = hIcon == IntPtr.Zero ? null : Icon.FromHandle(hIcon).Clone() as Icon;

91 if (phiconLarge[0] != IntPtr.Zero) DestroyIcon(phiconLarge[0]);

92 if (phiconSmall[0] != IntPtr.Zero) DestroyIcon(phiconSmall[0]);

93 }

94

95 return ico;

96 }

97

98 [DllImport("shell32.dll", SetLastError = true)]

99 private static extern uint ExtractIconEx(string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, uint nIcons);

100 [DllImport("User32.dll", SetLastError = true)]

101 private static extern uint DestroyIcon(IntPtr phicon);

View Code

怎么用同花顺炒股,最详细的流程来了!
侠盗猎车手5中文版(动作冒险游戏) v2.10.2 免费安卓版