如何用Python编写脚本批量自动化卸载Windows流氓软件

wmic在新版Windows中已弃用且无法查到多数流氓软件,应改用注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall及Wow6432Node读取,结合Publisher、UninstallString等字段精准识别并静默卸载。

subprocess 调用 wmic 卸载时为什么没反应?

因为 wmic 在较新 Windows 版本(尤其是 22H2+)中默认已弃用,且多数“流氓软件”不注册标准 Win32_Product 类,wmic product get name,identifyingnumber 基本查不到它们。强行调用只会返回空或超时。

实操建议:

  • 优先改用 Get-WmiObject Win32_Product(PowerShell)——但性能极差,且会触发 MSI 自检,可能卡死或误修复其他软件;不推荐用于批量
  • 真正可靠的方式是查注册表:所有安装信息集中在 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall 及其 Wow6432Node 子键
  • 用 Python 读取注册表时,必须以管理员权限运行脚本,否则无法访问 HKEY_LOCAL_MACHINE
  • 注意 32/64 位软件注册位置不同:Uninstall 下是 64 位项,Wow6432Node\Uninstall 下是 32 位项

如何精准识别“流氓软件”而不是误删系统组件?

不能只靠软件名关键词(如含“PC”“Boost”就删),很多正规工具也带这类词。关键看三处注册表值:

  • DisplayName:用户看到的名称,可作初筛
  • Publisher:重点字段,常见流氓厂商如 Advanced SystemCareIObitRevo Uninstaller Pro(非免费版)、AVG Secure Browser 等,需维护白名单/黑名单
  • UninstallStringQuietUninstallString:存在且非空,才说明支持静默卸载;若只有 ModifyPath 或为空,大概率只能手动点卸载界面

示例判断逻辑(伪代码):

elasticsearch-9.4.0 win

PHP中文网提供Elasticsearch 9.4.0 Windows 版本压缩包下载解压即用,内置 OpenJDK 无需额外配置 Java 环境。该版本重磅推出原生 Prometheus 支持、正式版 Elastic Workflows 以及基于 NVIDIA cuVS 的 GPU 加速向量索引,大幅提升 AI 检索与可观测性能力。建议前往官网下载,快速体验极速搜索与强大的数据分析功能。

if 'IObit' in publisher and uninstall_string and 'msiexec' not in uninstall_string.lower():
    # 可能是 IObit 的自定义安装器,尝试加 /S 参数
    cmd = f'"{uninstall_string}" /S'

静默卸载失败的常见错误和绕过方法

直接执行 UninstallString 常见报错:"The system cannot find the file specified",本质是路径含空格未加引号,或调用了相对路径的子程序。

  • 先用 shlex.split() 安全解析命令字符串,再用 subprocess.run(..., shell=False) 执行
  • 若卸载程序是 MSI 包,优先提取 ProductCode(IdentifyingNumber 值),用 msiexec /x {XXXX} /qn 静默移除
  • 遇到弹窗式卸载器(如某些国产安全软件),pyautogui 不稳定也不推荐;更稳妥的是用 psutil 监控进程启动,再发 WM_CLOSE 消息,但需额外依赖 GUI 权限
  • 部分软件(如 360、腾讯电脑管家)会检测是否被脚本调用,静默参数无效——此时只能标记为“需人工确认”,写入日志并跳过

为什么卸载后残留服务/启动项/计划任务?

注册表卸载项只管主程序,但流氓软件常额外注册:

  • 服务:检查 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services,按 DisplayNameImagePath 过滤关键词
  • 开机启动:扫描 RunRunOnce 键(SOFTWARE\Microsoft\Windows\CurrentVersion 下),以及 WOW6432Node 对应路径
  • 计划任务:用 schtasks /query /fo LIST /v 输出后解析,或用 win32com.client.Dispatch('Schedule.Service') 接口
  • 关键点:这些清理操作必须在主程序卸载**之后**执行,且服务需先 sc stopsc delete,顺序错会导致删除失败

最易忽略的是:某些软件把自身更新服务注册为“延迟启动”,脚本执行时服务尚未加载,sc query 查不到——得强制枚举所有服务项并匹配名称。

相关推荐:

如何在对象属性批量更新后仅执行一次回调函数

本文介绍一种优雅的 python 设计模式:通过私有属性 + 只读属性 + 显式 update() 方法,确保对象状态变更时回调函数(如数据校验、视图刷新等)仅被触发一次,避免重复计算,同时保持 ide 类型提示与代码可维护性。 本文介绍一种优雅的 python 设计模式:通过私有属性 + 只读属性 + 显式 update() 方法,确保对象状态变更时回调函数(如数据校验、视图刷新等)仅被触发一次...

如何确保对象属性批量更新后仅触发一次回调函数

本文介绍一种优雅的 Python 设计方案:通过禁用直接属性赋值 + 提供类型安全的 update() 方法,实现在多个属性变更后统一、且仅执行一次回调函数,兼顾 IDE 智能提示、代码可维护性与运行时可靠性。 本文介绍一种优雅的 python 设计方案:通过禁用直接属性赋值 + 提供类型安全的 `update()` 方法,实现在多个属性变更后统一、且仅执行一次回调函数,兼顾 ide 智能提示、代...

如何用Python自动化操作Word文档生成报告_利用python-docx模块

python-docx新建文档默认页边距1英寸、字体Calibri 11pt,因不加载normal.dotm模板而用硬编码值;需显式设置section边距和Normal样式字体;add_paragraph()自带段前段后间距致空行;cell.text会清空格式,应操作paragraphs[0].runs;样式名须严格匹配。 python-docx 能生成格式规整的 Word 报告,但不能读取或修改...

如何在 LlamaIndex 中正确使用 async/await 进行批量评估

在 LlamaIndex 中调用 aevaluate_queries() 等异步方法时,必须将 await 语句置于 async 函数内部,并通过 asyncio.run() 启动事件循环;直接在模块顶层 await 会导致 SyntaxError,这是 Python 异步语法的硬性限制。 在 llamaindex 中调用 `aevaluate_queries()` 等异步方法时,必须将 `awa...

如何用Python实现机器学习模型的数据漂移监控_集成AlibiDetect检测输入分布散度

TabularDrift比手动KL散度更可靠,因其采用MMD+RFF非参数检验,不假设分布、兼容混合特征并支持特征贡献分析;需正确配置cat_vars处理类别变量,且predict低延迟需优化。 AlibiDetect 的 TabularDrift 为什么比手动计算 KL 散度更可靠 直接用 scipy.stats.entropy 算训练集和线上 batch 的 KL 散度,结果波动大、阈值难设,...

如何用Python自动化监控Linux磁盘内存使用率并报警

psutil.disk_usage()通过statvfs()获取实时磁盘使用率,比df -h更准确;需传标准化绝对路径,监控应判连续阈值而非瞬时峰值,并以systemd Type=simple长期运行。 用 psutil 获取真实磁盘使用率,别信 df -h 的缓存值 Linux 的 df 命令默认显示的是挂载点的统计,但内核可能缓存了部分元数据,导致短时间重复调用结果滞后。而 psutil.di...

Python如何用KNN进行样本分类预测_KNeighborsClassifier找寻最近邻

KNeighborsClassifier预测不稳定主因是未标准化特征导致距离度量失真;需同步缩放训练测试集,合理选K值,注意高维稀疏数据及缺失值处理。 为什么 KNeighborsClassifier 预测结果不稳定? 默认情况下,KNeighborsClassifier 使用欧氏距离 + 未标准化特征,只要训练数据中某列量纲远大于其他列(比如年龄是 0–100,收入是 0–1000000),该列...

为什么Django的ORM不触发save方法_分析Python批量更新的局限性

update() 不触发 post_save 信号,因其绕过 ORM 实例层直接执行 SQL,不调用 save()、不实例化对象;save() 则触发信号、处理 auto_now 等逻辑,但并发下易覆盖字段,需用 update_fields 避免。 update() 方法根本不会调用模型的 save(),这是设计使然,不是 bug。它绕过 ORM 的实例层,直接拼 SQL 执行 —— 所以信号、a...

矩阵批量乘法:高效实现 M×3×3 与 M×3×1 的逐片矩阵-向量乘法

本文介绍如何使用 NumPy 的 np.matmul 实现批量矩阵-向量乘法,避免显式 Python 循环,在保持语义清晰的同时显著提升计算效率。适用于深度学习、几何变换等需对 M 组 3×3 矩阵分别作用于对应 3 维向量的场景。 本文介绍如何使用 numpy 的 `np.matmul` 实现批量矩阵-向量乘法,避免显式 python 循环,在保持语义清晰的同时显著提升计算效率。适用于深度学习、...