如何通过PowerShell从shell32.dll获取指定索引的图标?
从shell32.dll提取指定索引图标的解决方法
问题描述
我编写了一段从shell32.dll提取图标的PowerShell代码:
$iconPath = "$env:SystemRoot\system32\shell32.dll" # Path to the shell32.dll library $iconIndex = 4 # Index of the folder icon in the library $icon = [System.Drawing.Icon]::ExtractAssociatedIcon($iconPath) $icon = [System.Drawing.Icon]::new($icon, 16, 16)这段代码能从shell32.dll中获取图标,但未引用$iconIndex变量,无法获取索引为4的图标。尝试给ExtractAssociatedIcon添加第二个参数时出现报错,请问如何修改代码以获取指定索引的图标?
解决方案
.NET自带的ExtractAssociatedIcon方法只能提取文件关联的默认图标(通常是资源里的第一个图标),不支持指定索引。要提取特定索引的图标,需要调用Windows原生API ExtractIconEx,以下是修改后的代码:
Add-Type -TypeDefinition @" using System; using System.Drawing; using System.Runtime.InteropServices; public class IconExtractor { [DllImport("shell32.dll", CharSet = CharSet.Auto)] private static extern uint ExtractIconEx(string lpszFile, int nIconIndex, IntPtr[] phiconLarge, IntPtr[] phiconSmall, uint nIcons); [DllImport("user32.dll")] private static extern bool DestroyIcon(IntPtr hIcon); public static Icon ExtractIcon(string filePath, int iconIndex, bool isLargeIcon = false) { IntPtr[] iconHandles = new IntPtr[1]; uint extractedCount = ExtractIconEx(filePath, iconIndex, isLargeIcon ? iconHandles : null, isLargeIcon ? null : iconHandles, 1); if (extractedCount == 0 || iconHandles[0] == IntPtr.Zero) { throw new Exception("Failed to extract icon."); } try { return Icon.FromHandle(iconHandles[0]); } finally { DestroyIcon(iconHandles[0]); } } } "@ $iconPath = "$env:SystemRoot\system32\shell32.dll" $iconIndex = 4 $targetSize = 16 # 提取指定索引的小图标(要大图标就把最后一个参数改成$true) $rawIcon = [IconExtractor]::ExtractIcon($iconPath, $iconIndex, $false) # 调整到目标尺寸 $finalIcon = New-Object System.Drawing.Icon($rawIcon, $targetSize, $targetSize) # 示例:保存图标到文件 # $finalIcon.Save("C:\your_path\target_icon.ico") # 释放资源,避免内存泄漏 $rawIcon.Dispose() $finalIcon.Dispose()
代码说明
- 通过
Add-Type定义了IconExtractor类,封装了两个Win32 API调用:ExtractIconEx:从指定DLL文件中提取对应索引的图标,支持区分大、小图标。DestroyIcon:释放图标句柄,防止内存泄漏。
ExtractIcon方法返回提取到的Icon对象,之后可以通过System.Drawing.Icon的构造函数调整图标尺寸。- 最后必须调用
Dispose()释放图标资源,避免持续占用内存。
内容的提问来源于stack exchange,提问作者YorSubs
相关产品推荐
相关产品推荐

