
📅 前言
相信大家在使用 Windows 时都遇到过这种情况:直接删除了软件安装目录,或者卸载过程出错,导致“设置 -> 应用和功能”列表里依然残留着软件的图标。点击卸载,系统只会弹窗提示“找不到文件”,看着非常难受(强迫症噩梦)。
虽然市面上有各种管家类软件,但为了这点小功能装个大管家实在没必要。作为开发者,不如利用 Python 自己动手写一个轻量级的清理工具。
本文将复盘整个开发过程,包括 注册表扫描、UAC 管理员提权、Tkinter UI 美化 以及最终的 PyInstaller 打包。
🔗 项目源码
本项目已开源至 Gitee,欢迎 Star 和 Fork!
🛠️ 核心思路
Windows 的“添加/删除程序”列表,本质上是读取注册表中的特定路径。我们需要做的就是:
- 扫描:遍历
HKCU(当前用户) 和HKLM(本地机器) 下的Uninstall注册表项。 - 判断:读取每个软件的
InstallLocation(安装路径),检测该路径在磁盘上是否存在。如果不存在,判定为“失效”。 - 展示:通过 GUI 列表展示失效项,供用户勾选。
- 清理:调用 Windows API 删除选中的注册表项。
💻 实现细节
1. 注册表扫描 (winreg)
Python 自带的 winreg 模块足以应对。我们需要关注的路径通常是:
Software\Microsoft\Windows\CurrentVersion\Uninstall
import winreg
import os
# 扫描逻辑简化版
def scan():
scan_locations = [
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Uninstall"),
(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"),
# 还要注意 64位系统下的 32位应用注册表
(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall")
]
for hive, subkey in scan_locations:
# ... 遍历 EnumKey ...
# 读取 InstallLocation 并使用 os.path.exists 判断
2. 搞定管理员权限 (UAC)
要删除 HKEY_LOCAL_MACHINE 下的内容,必须拥有管理员权限。
为了体验更好,我实现了自动提权:程序启动时检测是否为 Admin,如果不是,则通过 ShellExecuteW 重新以管理员身份启动自己。
这里有个坑:脚本运行和打包后的 EXE 运行,提权参数是不一样的。
import ctypes
import sys
def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False
if __name__ == "__main__":
if is_admin():
# 启动主程序 UI
root = tk.Tk()
app = RegistryCleanerApp(root)
root.mainloop()
else:
# 请求提权
try:
if getattr(sys, 'frozen', False):
# 如果是打包后的 exe
script_param = None
else:
# 如果是 .py 脚本
script_param = f'"{__file__}"'
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, script_param, None, 1)
sys.exit()
except Exception as e:
print(f"Failed to elevate: {e}")
3. UI 交互与美化 (Tkinter + Pillow)
原生 Tkinter 的 Checkbutton 在 Treeview (列表控件) 中支持得并不好,而且在高分屏下非常小,难以点击。
解决方案:使用 Pillow 库动态绘制 24x24 像素的图片(选中/未选中状态),放入 Treeview 的第一列,模拟复选框。
from PIL import Image, ImageDraw, ImageTk
def create_checkbox_icons(self):
size = 24
# 绘制未选中方框
img_un = Image.new('RGBA', (size, size), (0, 0, 0, 0))
draw_un = ImageDraw.Draw(img_un)
draw_un.rectangle([2, 2, size-3, size-3], outline='#555555', width=2, fill='#FFFFFF')
self.icon_unchecked = ImageTk.PhotoImage(img_un)
# 绘制选中方框 (蓝色背景 + 白色对勾)
img_chk = Image.new('RGBA', (size, size), (0, 0, 0, 0))
draw_chk = ImageDraw.Draw(img_chk)
draw_chk.rectangle([2, 2, size-3, size-3], outline='#0078D7', width=2, fill='#0078D7')
# ... 画对勾逻辑 ...
self.icon_checked = ImageTk.PhotoImage(img_chk)
这样不仅解决了点击区域过小的问题,还让界面看起来更像现代的 Win11 风格。
4. 项目结构工程化
为了避免项目杂乱,我将源码和资源进行了分离:
regeditClean/
├── src/ # 源代码 (main.py 等)
├── assets/ # 资源文件 (图标、版本信息、截图)
├── build_config/ # PyInstaller 配置目录
├── dist/ # 最终 EXE 输出
└── requirements.txt # 依赖库
📦 PyInstaller 打包
最后一步是将 Python 脚本打包成独立的 .exe,方便在没有 Python 环境的电脑上使用。
为了让 EXE 看起来更正规,我做了以下几点:
- 自定义图标:生成了一个
.ico文件。 - 版本信息:创建
file_version_info.txt,写入版权和版本号。 - 配置文件分离:将
.spec文件生成到build_config目录,保持根目录整洁。
打包命令:
pyinstaller --noconsole --onefile ^
--name="RegCleanTool" ^
--icon="assets\app_icon.ico" ^
--version-file="assets\file_version_info.txt" ^
--specpath="build_config" ^
--distpath="dist" ^
--workpath="build" ^
src\main.py
🧪 安全测试
为了验证工具的可靠性,绝对不能拿自己的系统注册表开玩笑。
我编写了一个 create_test_entry.py 脚本,专门在 HKCU 下生成 5 个指向假路径的注册表项(例如指向 C:\Game\Ghost.exe)。通过“生成假数据 -> 扫描 -> 清理 -> 验证”的闭环测试,确保了工具逻辑的严密性。
🎉 最终效果
(这里可以插入您的运行截图 assets/runtime.png)
工具完美运行,成功识别并清理了测试生成的失效项,且 UI 清晰易用。
如果你觉得这个小工具对你有帮助,或者想研究下源码,欢迎访问我的 Gitee 仓库:
👉 https://gitee.com/sen2020/regedit-clean
标签: Python, Tkinter, 注册表清理, PyInstaller, 开源工具, Windows开发

被折叠的 条评论
为什么被折叠?



