如何使用Python获取Windows系统中任意文件/可执行文件的图标
如何使用Python获取Windows系统中任意文件/可执行文件的图标
嘿,我完全懂你在打造替代桌面Shell时的痛点——只靠icoextract只能搞定EXE文件的图标,文件夹、Word文档还有微软商店应用这些类型的图标怎么拿确实让人头疼。我之前做类似项目时也踩过这些坑,给你分享几个实用的解决方案:
方法一:用PyWin32调用Windows Shell API(最可靠的原生方案)
Windows本身的Shell API就提供了获取任意文件图标的能力,不管是系统默认关联的图标,还是微软商店应用的图标都能搞定。你需要先安装pywin32库:
pip install pywin32
下面是一个可以获取任意文件/文件夹图标的示例代码,它会把图标保存为本地ICO文件:
import win32api import win32gui import win32con import win32ui def get_file_icon(file_path, save_path="icon.ico", icon_size=(32, 32)): # 根据图标尺寸选择对应标识 flag = win32con.SHGFI_ICON | (win32con.SHGFI_LARGEICON if icon_size[0] >= 32 else win32con.SHGFI_SMALLICON) # 获取文件的图标信息 shinfo = win32api.SHGetFileInfo(file_path, 0, flag) hicon = shinfo[0] # 创建图标绘制所需的设备上下文 hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0)) hbmp = win32ui.CreateBitmap() hbmp.CreateCompatibleBitmap(hdc, icon_size[0], icon_size[1]) hdc = hdc.CreateCompatibleDC() # 将图标绘制到位图中 hdc.SelectObject(hbmp) hdc.DrawIcon((0, 0), hicon) # 保存为ICO文件 hbmp.SaveBitmapFile(hdc, save_path) # 释放系统资源 win32gui.DestroyIcon(hicon) # 测试示例 get_file_icon("C:\\Users\\YourName\\Desktop\\test.docx", "docx_icon.ico") get_file_icon("C:\\Users\\YourName\\Documents", "folder_icon.ico") # 微软商店应用直接传入其URI即可 get_file_icon("ms-windows-store://pdp/?ProductId=9WZDNCRFJBMP", "store_app.ico")
这个方法的优势是原生支持所有Windows文件类型,包括微软商店应用(直接传入它们的URI即可),不需要手动处理注册表或者文件关联,省心又靠谱。
方法二:通过注册表读取文件类型的默认图标
如果不想依赖PyWin32,也可以用Python自带的winreg模块读取注册表中文件类型对应的默认图标路径。不过这个方法需要处理一些变量替换(比如注册表中的%1、SystemRoot等占位符),步骤稍繁琐:
import winreg import os def get_default_icon_from_registry(file_extension): try: # 打开扩展名对应的注册表项 with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, file_extension) as ext_key: # 获取该扩展名关联的文件类型(比如.docx对应Word.Document.12) file_type = winreg.QueryValue(ext_key, None) # 打开该文件类型下的DefaultIcon项 with winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, f"{file_type}\\DefaultIcon") as icon_key: icon_info = winreg.QueryValue(icon_key, None) # 替换路径中的系统环境变量占位符 icon_info = os.path.expandvars(icon_info) # 处理类似"path.ico,0"的格式,逗号后是图标在文件中的索引 if "," in icon_info: icon_path, icon_index = icon_info.split(",", 1) icon_index = int(icon_index.strip()) else: icon_path = icon_info icon_index = 0 return icon_path, icon_index except FileNotFoundError: # 如果找不到对应项,返回系统默认图标 return "C:\\Windows\\System32\\shell32.dll", 0 # 测试示例 docx_icon_path, docx_icon_index = get_default_icon_from_registry(".docx") print(f"Word文档图标路径:{docx_icon_path},索引:{docx_icon_index}")
拿到图标路径和索引后,你可以用Pillow库提取并保存图标:
pip install pillow
提取代码示例:
from PIL import Image def extract_icon_from_file(icon_path, icon_index, save_path="icon.ico"): with Image.open(icon_path) as img: if img.format == "ICO": # 如果是ICO文件,直接定位到指定索引保存 img.seek(icon_index) img.save(save_path) else: # 如果是DLL/EXE文件,提取对应索引的图标 icon = img.getdata()[icon_index] icon.save(save_path) # 提取Word文档图标 extract_icon_from_file(docx_icon_path, docx_icon_index, "docx_icon_reg.ico")
不过这个方法有个明显缺点:无法直接处理微软商店应用,因为它们的图标不是通过注册表关联的,所以还是更推荐第一种方法。
小提示
- 对于微软商店应用,你可以从快捷方式的目标路径拿到类似
ms-windows-store://xxx的URI,直接传入第一种方法的get_file_icon函数就能获取图标。 - 如果需要不同尺寸的图标,只需要修改
icon_size参数,比如(16,16)是系统小图标,(256,256)是高清大图标。
备注:内容来源于stack exchange,提问作者KillerRebooted




