Windows已安装应用图标缺失:如何优化代码或采用替代方案?
解决Windows已安装应用图标获取不全的问题
一、优化注册表查询逻辑
仅读取DisplayIcon键的局限性很大,多数应用不会在卸载项中直接配置该字段,你需要扩展查询范围并增加 fallback 逻辑:
覆盖更多注册表路径
应用的卸载信息可能分布在多个位置,必须同时遍历:HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall(系统级应用)HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall(64位系统上的32位应用)HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall(用户级安装的应用)
处理
DisplayIcon的格式问题
部分应用的DisplayIcon值会附带图标索引(比如"C:\xxx\app.exe,0"),需要先分割出实际文件路径:if "," in display_icon: display_icon = display_icon.split(",")[0].strip('"')从
InstallLocationfallback 找主程序
当没有DisplayIcon时,读取InstallLocation字段,然后在该目录下查找主程序EXE:- 优先匹配常见主程序名(如
chrome.exe、steam.exe) - 匹配失败时遍历目录查找EXE文件
- 优先匹配常见主程序名(如
二、基于PyQt6的完整实现代码
结合Qt原生的图标获取能力,无需额外调用复杂的Windows API:
import winreg import os from PyQt6.QtWidgets import QApplication, QComboBox, QWidget, QVBoxLayout from PyQt6.QtGui import QIcon, QFileIconProvider from PyQt6.QtCore import QFileInfo def get_installed_apps(): apps = [] # 定义需要遍历的注册表路径 reg_paths = [ r"Software\Microsoft\Windows\CurrentVersion\Uninstall", r"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" ] root_keys = [winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER] for root_key in root_keys: for reg_path in reg_paths: try: parent_key = winreg.OpenKey(root_key, reg_path) subkey_count = winreg.QueryInfoKey(parent_key)[0] for i in range(subkey_count): subkey_name = winreg.EnumKey(parent_key, i) try: subkey = winreg.OpenKey(parent_key, subkey_name) # 必须获取DisplayName,否则跳过该条目 display_name = winreg.QueryValueEx(subkey, "DisplayName")[0] # 尝试读取DisplayIcon display_icon = None try: icon_val = winreg.QueryValueEx(subkey, "DisplayIcon")[0] display_icon = icon_val.split(",")[0].strip('"') if "," in icon_val else icon_val.strip('"') except FileNotFoundError: pass # 从InstallLocation查找主程序 if not display_icon: try: install_loc = winreg.QueryValueEx(subkey, "InstallLocation")[0] if os.path.isdir(install_loc): # 优先匹配常见主程序名 common_exes = ["chrome.exe", "steam.exe", "firefox.exe", "main.exe"] for exe in common_exes: exe_path = os.path.join(install_loc, exe) if os.path.exists(exe_path): display_icon = exe_path break # 找不到则遍历目录找第一个EXE if not display_icon: for root, _, files in os.walk(install_loc): for f in files: if f.lower().endswith(".exe"): display_icon = os.path.join(root, f) break if display_icon: break except FileNotFoundError: pass apps.append((display_name, display_icon)) except FileNotFoundError: continue finally: subkey.Close() except FileNotFoundError: continue finally: parent_key.Close() # 去重并按名称排序 unique_apps = list({name: icon for name, icon in apps}.items()) return sorted(unique_apps, key=lambda x: x[0]) def fill_combo_box(combo): apps = get_installed_apps() icon_provider = QFileIconProvider() for name, icon_path in apps: icon = QIcon() if icon_path and os.path.exists(icon_path): file_info = QFileInfo(icon_path) icon = icon_provider.icon(file_info) combo.addItem(icon, name) if __name__ == "__main__": app = QApplication([]) window = QWidget() layout = QVBoxLayout() combo = QComboBox() fill_combo_box(combo) layout.addWidget(combo) window.setLayout(layout) window.resize(400, 300) window.show() app.exec()
三、额外优化方案
处理UWP应用
UWP应用的信息不在常规卸载路径中,需要读取HKLM\Software\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore\Applications,从PackageFullName对应的InstallLocation中找到Assets目录下的图标文件(如Logo.png)。使用Windows原生API获取图标
如果需要更精准的系统原生图标,可以用pywin32调用SHGetFileInfo:import win32gui import win32con from PyQt6.QtGui import QPixmap def get_native_icon(file_path): shinfo = win32gui.SHGetFileInfo(file_path, 0, win32con.SHGFI_ICON | win32con.SHGFI_LARGEICON) hicon = shinfo[0] pixmap = QPixmap.fromWinHICON(hicon) win32gui.DestroyIcon(hicon) return QIcon(pixmap)
内容的提问来源于stack exchange,提问作者Edward
相关产品推荐
相关产品推荐

