老师
快乐
卸载360安全卫士后 如何快速清理其残留的文件? – 海南仙岛

卸载360安全卫士后 如何快速清理其残留的文件?

2025年09月10日

原创内容,转载请注明出处:https://www.myzhenai.com.cn/post/4810.html

我有个习惯,我会偶尔使用360安全卫士,只用它里边有软件管家进行升级,一用完我就会卸载360安全卫士

我知道360安全卫士会在系统盘中残留很多目录、文件,同时它有一些sys驱动文件会残留在系统重要目录中

同时注册表中也会残留非常多的数据

当你卸载了360安全卫士后,这些东西还保存在你的系统之中

我不知道为什么360官方开发人员为什么不在卸载程序中删除这些残留文件

程序和源代码下载:

通过网盘分享的文件:360cleaner
链接: https://pan.baidu.com/s/14gZYAsjnpnOIahAMKBtTnA?pwd=25xy 提取码: 25xy
–来自百度网盘超级会员v10的分享

以下是我找到的360给我们系统中残留下来的一些目录、文件、注册表信息

C:\360SANDBOX\
C:\$360Section\
C:\Program Files (x86)\360\
C:\ProgramData\360safe\
C:\ProgramData\360SD\
C:\Users\All Users\360safe\
C:\Users\All Users\360SD\
C:\Users\RucLinuxs\AppData\LocalLow\360WD\
C:\Users\RucLinuxs\AppData\Roaming\360DesktopLite\
C:\Users\RucLinuxs\AppData\Roaming\360Login\
C:\Users\RucLinuxs\AppData\Roaming\360Quarant\
C:\Users\RucLinuxs\AppData\Roaming\360Safe\
C:\Windows\Tasks\360Disabled\

C:\Windows\System32\drivers\360AntiHacker64.sys
C:\Windows\System32\drivers\360AntiHijack64.sys
C:\Windows\System32\drivers\360AntiSteal64.sys
C:\Windows\System32\drivers\360Box64.sys
C:\Windows\System32\drivers\360Camera64.sys
C:\Windows\System32\drivers\360elam64.sys
C:\Windows\System32\drivers\360FsFlt.sys
C:\Windows\System32\drivers\360Hvm64.dat
C:\Windows\System32\drivers\360Hvm64.sys
C:\Windows\System32\drivers\360netmon.sys
C:\Windows\System32\drivers\360qpesv64.sys
C:\Windows\System32\drivers\360Sensor64.sys


计算机\HKEY_CLASSES_ROOT\*\shellex\ContextMenuHandlers\Safe360Ext
计算机\HKEY_CLASSES_ROOT\.360SafeUAP
计算机\HKEY_CLASSES_ROOT\360Safe.ext.1
计算机\HKEY_CLASSES_ROOT\360SafeLive.Update
计算机\HKEY_CLASSES_ROOT\360SafeLive.Update.2
计算机\HKEY_CLASSES_ROOT\AppID\shell360ext.DLL
计算机\HKEY_CLASSES_ROOT\CLSID\{039219EC-5F9A-460E-8C72-86D5DC7B8683}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{039219EC-5F9A-460E-8C72-86D5DC7B8683}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{039219EC-5F9A-460E-8C72-86D5DC7B8683}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{056A6FBD-8148-443A-AAB2-DB3C46B1F083}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{056A6FBD-8148-443A-AAB2-DB3C46B1F083}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{056A6FBD-8148-443A-AAB2-DB3C46B1F083}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{06F2A2CA-E0E2-47D7-A3EC-29FD090E7F86}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{06F2A2CA-E0E2-47D7-A3EC-29FD090E7F86}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{06F2A2CA-E0E2-47D7-A3EC-29FD090E7F86}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{12793398-A212-446F-BA1E-1F1B5ABDB89C}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{12793398-A212-446F-BA1E-1F1B5ABDB89C}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{12793398-A212-446F-BA1E-1F1B5ABDB89C}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{12DE9E3C-5119-424b-93A5-D72E3D005558}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{12DE9E3C-5119-424b-93A5-D72E3D005558}\Shell\Delete\Command
计算机\HKEY_CLASSES_ROOT\CLSID\{12DE9E3C-5119-424b-93A5-D72E3D005558}\Shell\Open\Command
计算机\HKEY_CLASSES_ROOT\CLSID\{26CD0715-0722-479B-A8C7-29A911171774}\InProcServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{2A650B6F-1548-4294-AB07-F17604108156}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{2A650B6F-1548-4294-AB07-F17604108156}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{2A650B6F-1548-4294-AB07-F17604108156}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{47F57C45-E7A1-4414-A6F0-A0865F6E4CA6}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{47F57C45-E7A1-4414-A6F0-A0865F6E4CA6}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{47F57C45-E7A1-4414-A6F0-A0865F6E4CA6}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{4D88ED58-E7F0-4EF2-AE06-5D5873AD19C6}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{4D88ED58-E7F0-4EF2-AE06-5D5873AD19C6}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{4D88ED58-E7F0-4EF2-AE06-5D5873AD19C6}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{55F9A4E2-52B3-4743-9EA7-2FEE413DABB6}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{55F9A4E2-52B3-4743-9EA7-2FEE413DABB6}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{55F9A4E2-52B3-4743-9EA7-2FEE413DABB6}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{5E19C0CE-C02C-46c2-98C3-A2E12EDE0E17}
计算机\HKEY_CLASSES_ROOT\CLSID\{63A39D0C-0B63-49EE-BB21-D106ED548C51}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{63A39D0C-0B63-49EE-BB21-D106ED548C51}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{63A39D0C-0B63-49EE-BB21-D106ED548C51}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\shell\深度清理垃圾
计算机\HKEY_CLASSES_ROOT\CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\shell\深度清理垃圾\command
计算机\HKEY_CLASSES_ROOT\CLSID\{6A377734-9D9D-44AE-A69C-06E81F6C8064}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{6A377734-9D9D-44AE-A69C-06E81F6C8064}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{6A377734-9D9D-44AE-A69C-06E81F6C8064}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{6bd299cd-1997-4cc6-834c-e3c1c6ba0ea5}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{78A1990F-7561-4CB9-A8BF-B6CCF8AAEB97}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{7A148181-CEB9-4F5E-B5F2-CDC5B68BD3A8}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{7A148181-CEB9-4F5E-B5F2-CDC5B68BD3A8}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{7A148181-CEB9-4F5E-B5F2-CDC5B68BD3A8}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{7C0F6D57-E799-4C8A-A319-8E2B4D724CF0}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{826D8B56-A99E-4CD2-8F38-CFCE2A7B89C4}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{826D8B56-A99E-4CD2-8F38-CFCE2A7B89C4}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{826D8B56-A99E-4CD2-8F38-CFCE2A7B89C4}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{86A06468-8A7C-4EFA-A61C-9C0E911194C9}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{86A06468-8A7C-4EFA-A61C-9C0E911194C9}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{86A06468-8A7C-4EFA-A61C-9C0E911194C9}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{A0AB8231-8E73-410D-8D1C-BE1027EA19A3}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{A0AB8231-8E73-410D-8D1C-BE1027EA19A3}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{A0AB8231-8E73-410D-8D1C-BE1027EA19A3}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{A23CB8EB-C9C4-475D-88C0-CC51933F2D9E}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{A23CB8EB-C9C4-475D-88C0-CC51933F2D9E}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{A23CB8EB-C9C4-475D-88C0-CC51933F2D9E}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{AF1859F5-DF30-4EEC-9404-E5F32FD260B7}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{AF1859F5-DF30-4EEC-9404-E5F32FD260B7}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{AF1859F5-DF30-4EEC-9404-E5F32FD260B7}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{C0B3184D-90C8-4F4D-B19A-42B6C659378B}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{C0B3184D-90C8-4F4D-B19A-42B6C659378B}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{C0B3184D-90C8-4F4D-B19A-42B6C659378B}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{C9A94B6A-60FB-4A19-8BA3-4A2068F1026D}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{C9A94B6A-60FB-4A19-8BA3-4A2068F1026D}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{C9A94B6A-60FB-4A19-8BA3-4A2068F1026D}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{CC00F81D-5262-450A-B1FA-D6BEE3406263}
计算机\HKEY_CLASSES_ROOT\CLSID\{CC00F81D-5262-450A-B1FA-D6BEE3406263}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{D1FD8167-E560-4B08-9F4E-CA89F979BD84}
计算机\HKEY_CLASSES_ROOT\CLSID\{D1FD8167-E560-4B08-9F4E-CA89F979BD84}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{D8A9DF39-075A-4C8C-B48B-8121C37FFDF0}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{D8A9DF39-075A-4C8C-B48B-8121C37FFDF0}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{D8A9DF39-075A-4C8C-B48B-8121C37FFDF0}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{E431A037-AE60-4D57-99D7-B402223AE8A0}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{E431A037-AE60-4D57-99D7-B402223AE8A0}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{E431A037-AE60-4D57-99D7-B402223AE8A0}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{E715FE74-087F-4F4C-BB0A-0245C8A897E2}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{E715FE74-087F-4F4C-BB0A-0245C8A897E2}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{E715FE74-087F-4F4C-BB0A-0245C8A897E2}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{EE3F69E2-3085-4C46-B050-A45F008827D6}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{EE3F69E2-3085-4C46-B050-A45F008827D6}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{EE3F69E2-3085-4C46-B050-A45F008827D6}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{EEE8C32E-C785-4B1F-A33B-FCD6942418BD}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{EEE8C32E-C785-4B1F-A33B-FCD6942418BD}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{EEE8C32E-C785-4B1F-A33B-FCD6942418BD}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{F6BC477E-2646-459A-9D6A-75902C24430D}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{F6BC477E-2646-459A-9D6A-75902C24430D}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{F6BC477E-2646-459A-9D6A-75902C24430D}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{FA1B1706-967F-4834-8405-2343A38E4086}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{FA1B1706-967F-4834-8405-2343A38E4086}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{FA1B1706-967F-4834-8405-2343A38E4086}\Shell\Open
计算机\HKEY_CLASSES_ROOT\CLSID\{FD6A8A28-DB7F-478C-A358-C989EFE02096}\DefaultIcon
计算机\HKEY_CLASSES_ROOT\CLSID\{FD6A8A28-DB7F-478C-A358-C989EFE02096}\InprocServer32
计算机\HKEY_CLASSES_ROOT\CLSID\{FD6A8A28-DB7F-478C-A358-C989EFE02096}\Shell\Open
计算机\HKEY_CLASSES_ROOT\Folder\ShellEx\ContextMenuHandlers\Safe360Ext
计算机\HKEY_CLASSES_ROOT\lnkfile\shellex\ContextMenuHandlers\Safe360Ext
计算机\HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\Shell\MuiCache  这里有一些360的键值
计算机\HKEY_CLASSES_ROOT\qsdis\DefaultIcon
计算机\HKEY_CLASSES_ROOT\qsdis\shell\open\command
计算机\HKEY_CLASSES_ROOT\qsoftmgr\shell\open\command
计算机\HKEY_CLASSES_ROOT\softmanager360
计算机\HKEY_CLASSES_ROOT\softmanager360\DefaultIcon
计算机\HKEY_CLASSES_ROOT\softmanager360\Shell\Open\Command
计算机\HKEY_CLASSES_ROOT\TypeLib\{338CE0CA-987B-4CC9-8297-5430E7DCFD2A}\1.0\0\win32
计算机\HKEY_CLASSES_ROOT\TypeLib\{338CE0CA-987B-4CC9-8297-5430E7DCFD2A}\1.0\0\win64
计算机\HKEY_CLASSES_ROOT\TypeLib\{338CE0CA-987B-4CC9-8297-5430E7DCFD2A}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\TypeLib\{42133F20-66FA-4755-9B06-35D6CE360630}\1.0\0\win32
计算机\HKEY_CLASSES_ROOT\TypeLib\{42133F20-66FA-4755-9B06-35D6CE360630}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\TypeLib\{749B9DBD-EBDC-4324-A3C3-95BF9E8234B1}\1.0\0\win32
计算机\HKEY_CLASSES_ROOT\TypeLib\{749B9DBD-EBDC-4324-A3C3-95BF9E8234B1}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\TypeLib\{90FA8B71-C512-4D04-BE3F-3E2CFE7487C1}\1.0\0\win64
计算机\HKEY_CLASSES_ROOT\TypeLib\{90FA8B71-C512-4D04-BE3F-3E2CFE7487C1}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{26CD0715-0722-479B-A8C7-29A911171774}\InProcServer32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{467B32FF-C688-40FF-95FC-C7C61247B0AA}\InprocServer32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{7C0F6D57-E799-4C8A-A319-8E2B4D724CF0}\InprocServer32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{87515F61-A66C-4319-A0E0-D416CB8059E3}
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{87515F61-A66C-4319-A0E0-D416CB8059E3}\InprocServer32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{87515F61-A66C-4319-A0E0-D416CB8059E3}\ProgID
计算机\HKEY_CLASSES_ROOT\WOW6432Node\CLSID\{87515F61-A66C-4319-A0E0-D416CB8059E3}\VersionIndependentProgID
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{338CE0CA-987B-4CC9-8297-5430E7DCFD2A}\1.0\0\win32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{338CE0CA-987B-4CC9-8297-5430E7DCFD2A}\1.0\0\win64
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{338CE0CA-987B-4CC9-8297-5430E7DCFD2A}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{42133F20-66FA-4755-9B06-35D6CE360630}\1.0\0\win32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{42133F20-66FA-4755-9B06-35D6CE360630}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{749B9DBD-EBDC-4324-A3C3-95BF9E8234B1}\1.0\0\win32
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{749B9DBD-EBDC-4324-A3C3-95BF9E8234B1}\1.0\HELPDIR
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{90FA8B71-C512-4D04-BE3F-3E2CFE7487C1}\1.0\0\win64
计算机\HKEY_CLASSES_ROOT\WOW6432Node\TypeLib\{90FA8B71-C512-4D04-BE3F-3E2CFE7487C1}\1.0\HELPDIR
计算机\HKEY_CURRENT_USER\Software
计算机\HKEY_CURRENT_USER\Software\360safe
计算机\HKEY_CURRENT_USER\Software\360se6
计算机\HKEY_CURRENT_USER\Software\360SoftMgr
计算机\HKEY_CURRENT_USER\Software\551c591f-97e9-46bf-909d-9e4f7b016ca9\360qudongdashi
计算机\HKEY_CURRENT_USER\Software\Classes\.360SafeUAP
计算机\HKEY_CURRENT_USER\Software\Classes\360Safe.ext.1
计算机\HKEY_CURRENT_USER\Software\Classes\360Safe.ext.1\shell\open\command
计算机\HKEY_CURRENT_USER\Software\Classes\Local Settings\Software\Microsoft\Windows\Shell\MuiCache 这个项下有很多360的键值
计算机\HKEY_CURRENT_USER\Software\Classes\qsdis\shell\open\command
计算机\HKEY_CURRENT_USER\Software\Classes\qsoftmgr\DefaultIcon
计算机\HKEY_CURRENT_USER\Software\Classes\qsoftmgr\shell\open\command
计算机\HKEY_CURRENT_USER\Software\LiveUpdate360
计算机\HKEY_CURRENT_USER\Software\Microsoft\DirectX\UserGpuPreferences
计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FeatureUsage\AppSwitched  这项下有些360的键值
计算机\HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Store 这项下有些360的键值
计算机\HKEY_CURRENT_USER\Software\MozillaPlugins\@360.cn/360SoftMgrPlugin
计算机\HKEY_CURRENT_USER\Software\MozillaPlugins\@360.cn/360SoftMgrPlugin\MimeTypes\application/360softmgrplugin
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\*\shellex\ContextMenuHandlers\Safe360Ext
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\360SafeLive.Update
计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Classes\360SafeLive.Update.2
计算机\HKEY_USERS\360SandBox
计算机\HKEY_USERS\360SPDM

这些东西在用户卸载360后,重启系统照样还能找到

我把这些内容交给了通义千问、Kimi、DeepSeek,让它们生成相应的清理软件

下边我把打包好的软件和源码全发出来,大家可以参考使用

代码运行和打包,请安装以下的包

pip install Pyqt5 pyinstaller pywin32

注:注册表操作风险很高,此次涉及的注册表有其他共用关系,删除前请注意

DeepSeek

import os
import sys
import winreg
import shutil
import logging
from pathlib import Path
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QCheckBox, QPushButton, QTreeWidget, QTreeWidgetItem, QLabel,
                             QMessageBox, QSplitter, QProgressBar, QFileDialog)
from PyQt5.QtCore import Qt, QThread, pyqtSignal
from PyQt5.QtGui import QFont

# 设置日志
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

class CleanerThread(QThread):
    """执行清理工作的线程"""
    progress_signal = pyqtSignal(int, str)
    finished_signal = pyqtSignal(bool, str)
    
    def __init__(self, items_to_clean):
        super().__init__()
        self.items_to_clean = items_to_clean
        self.total_items = len(items_to_clean)
    
    def run(self):
        success_count = 0
        total = self.total_items
        
        for i, item in enumerate(self.items_to_clean):
            item_type, path = item
            self.progress_signal.emit(int((i / total) * 100), f"处理: {path}")
            
            try:
                if item_type == "file":
                    if os.path.exists(path):
                        os.remove(path)
                        success_count += 1
                        logging.info(f"已删除文件: {path}")
                elif item_type == "directory":
                    if os.path.exists(path):
                        shutil.rmtree(path)
                        success_count += 1
                        logging.info(f"已删除目录: {path}")
                elif item_type == "registry":
                    try:
                        # 解析注册表路径
                        if path.startswith("HKEY_CURRENT_USER"):
                            root = winreg.HKEY_CURRENT_USER
                            subkey = path[18:]
                        elif path.startswith("HKEY_LOCAL_MACHINE"):
                            root = winreg.HKEY_LOCAL_MACHINE
                            subkey = path[19:]
                        elif path.startswith("HKEY_CLASSES_ROOT"):
                            root = winreg.HKEY_CLASSES_ROOT
                            subkey = path[18:]
                        else:
                            continue
                            
                        # 删除注册表项
                        if "\\" in subkey:
                            key_path, value_name = subkey.rsplit("\\", 1)
                            try:
                                key = winreg.OpenKey(root, key_path, 0, winreg.KEY_ALL_ACCESS)
                                winreg.DeleteValue(key, value_name)
                                winreg.CloseKey(key)
                            except FileNotFoundError:
                                pass  # 键值不存在,忽略
                            except WindowsError:
                                # 尝试删除整个项
                                try:
                                    winreg.DeleteKey(root, subkey)
                                except WindowsError:
                                    pass  # 无法删除,可能需要权限或不存在
                        else:
                            try:
                                winreg.DeleteKey(root, subkey)
                            except WindowsError:
                                pass  # 无法删除,可能需要权限或不存在
                                
                        success_count += 1
                        logging.info(f"已处理注册表: {path}")
                    except Exception as e:
                        logging.error(f"处理注册表失败 {path}: {e}")
            except Exception as e:
                logging.error(f"处理失败 {path}: {e}")
        
        self.progress_signal.emit(100, "清理完成")
        self.finished_signal.emit(True, f"清理完成! 成功处理 {success_count}/{total} 个项目")

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("360安全卫士残留清理工具")
        self.setGeometry(100, 100, 900, 600)
        
        # 中心部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        
        # 标题
        title_label = QLabel("360安全卫士残留清理工具")
        title_font = QFont()
        title_font.setPointSize(16)
        title_font.setBold(True)
        title_label.setFont(title_font)
        title_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(title_label)
        
        # 说明
        desc_label = QLabel("请选择要清理的360安全卫士残留文件和注册表项:")
        main_layout.addWidget(desc_label)
        
        # 创建分割器
        splitter = QSplitter(Qt.Vertical)
        main_layout.addWidget(splitter)
        
        # 文件树
        self.file_tree = QTreeWidget()
        self.file_tree.setHeaderLabels(["选择", "类型", "路径"])
        self.file_tree.setColumnWidth(0, 100)
        self.file_tree.setColumnWidth(1, 80)
        splitter.addWidget(self.file_tree)
        
        # 进度区域
        progress_widget = QWidget()
        progress_layout = QVBoxLayout(progress_widget)
        
        self.progress_bar = QProgressBar()
        self.status_label = QLabel("准备就绪")
        progress_layout.addWidget(self.progress_bar)
        progress_layout.addWidget(self.status_label)
        
        splitter.addWidget(progress_widget)
        splitter.setSizes([400, 100])
        
        # 按钮区域
        button_layout = QHBoxLayout()
        main_layout.addLayout(button_layout)
        
        self.select_all_btn = QPushButton("全选")
        self.select_all_btn.clicked.connect(self.select_all)
        button_layout.addWidget(self.select_all_btn)
        
        self.deselect_all_btn = QPushButton("全不选")
        self.deselect_all_btn.clicked.connect(self.deselect_all)
        button_layout.addWidget(self.deselect_all_btn)
        
        self.scan_btn = QPushButton("重新扫描")
        self.scan_btn.clicked.connect(self.scan_system)
        button_layout.addWidget(self.scan_btn)
        
        self.clean_btn = QPushButton("开始清理")
        self.clean_btn.clicked.connect(self.start_cleaning)
        button_layout.addWidget(self.clean_btn)
        
        self.export_btn = QPushButton("导出列表")
        self.export_btn.clicked.connect(self.export_list)
        button_layout.addWidget(self.export_btn)
        
        # 初始化数据
        self.clean_items = []
        self.scan_system()
    
    def scan_system(self):
        """扫描系统中的360残留"""
        self.file_tree.clear()
        self.clean_items = []
        
        # 常见的360残留路径 (基于用户提供的列表)
        common_paths = [
            # 目录
            ("directory", "C:\\360SANDBOX\\"),
            ("directory", "C:\\$360Section\\"),
            ("directory", "C:\\Program Files (x86)\\360\\"),
            ("directory", "C:\\ProgramData\\360safe\\"),
            ("directory", "C:\\ProgramData\\360SD\\"),
            ("directory", "C:\\Users\\All Users\\360safe\\"),
            ("directory", "C:\\Users\\All Users\\360SD\\"),
            ("directory", "C:\\Users\\{}\\AppData\\LocalLow\\360WD\\".format(os.getlogin())),
            ("directory", "C:\\Users\\{}\\AppData\\Roaming\\360DesktopLite\\".format(os.getlogin())),
            ("directory", "C:\\Users\\{}\\AppData\\Roaming\\360Login\\".format(os.getlogin())),
            ("directory", "C:\\Users\\{}\\AppData\\Roaming\\360Quarant\\".format(os.getlogin())),
            ("directory", "C:\\Users\\{}\\AppData\\Roaming\\360Safe\\".format(os.getlogin())),
            ("directory", "C:\\Windows\\Tasks\\360Disabled\\"),
            
            # 文件
            ("file", "C:\\Windows\\System32\\drivers\\360AntiHacker64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360AntiHijack64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360AntiSteal64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360Box64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360Camera64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360elam64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360FsFlt.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360Hvm64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360netmon.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360qpesv64.sys"),
            ("file", "C:\\Windows\\System32\\drivers\\360Sensor64.sys"),
        ]
        
        # 常见的360注册表项
        registry_paths = [
            # 这里添加一部分常见的注册表路径,实际应用中应该更全面
            ("registry", "HKEY_CURRENT_USER\\Software\\360safe"),
            ("registry", "HKEY_CURRENT_USER\\Software\\360se6"),
            ("registry", "HKEY_CURRENT_USER\\Software\\360SoftMgr"),
            ("registry", "HKEY_LOCAL_MACHINE\\SOFTWARE\\360safe"),
            ("registry", "HKEY_LOCAL_MACHINE\\SOFTWARE\\360SD"),
        ]
        
        # 检查项目是否存在并添加到列表
        all_items = common_paths + registry_paths
        
        for item_type, path in all_items:
            exists = False
            
            if item_type in ["file", "directory"]:
                exists = os.path.exists(path)
            elif item_type == "registry":
                # 简化检查,实际应该尝试打开注册表项
                exists = True  # 假设存在,让用户决定
            
            if exists or item_type == "registry":  # 对于注册表项,即使不确定是否存在也显示
                self.add_item_to_tree(item_type, path)
                self.clean_items.append((item_type, path))
        
        self.status_label.setText("扫描完成。找到 {} 个可能残留的项目".format(len(self.clean_items)))
    
    def add_item_to_tree(self, item_type, path):
        """添加项目到树形控件"""
        item = QTreeWidgetItem(self.file_tree)
        item.setCheckState(0, Qt.Checked)
        
        # 类型列
        item.setText(1, item_type)
        
        # 路径列
        item.setText(2, path)
        
        # 存储原始数据
        item.setData(0, Qt.UserRole, (item_type, path))
    
    def select_all(self):
        """选择所有项目"""
        for i in range(self.file_tree.topLevelItemCount()):
            item = self.file_tree.topLevelItem(i)
            item.setCheckState(0, Qt.Checked)
    
    def deselect_all(self):
        """取消选择所有项目"""
        for i in range(self.file_tree.topLevelItemCount()):
            item = self.file_tree.topLevelItem(i)
            item.setCheckState(0, Qt.Unchecked)
    
    def get_selected_items(self):
        """获取选中的项目"""
        selected = []
        for i in range(self.file_tree.topLevelItemCount()):
            item = self.file_tree.topLevelItem(i)
            if item.checkState(0) == Qt.Checked:
                item_type, path = item.data(0, Qt.UserRole)
                selected.append((item_type, path))
        return selected
    
    def start_cleaning(self):
        """开始清理选中的项目"""
        selected_items = self.get_selected_items()
        if not selected_items:
            QMessageBox.warning(self, "警告", "请先选择要清理的项目")
            return
        
        reply = QMessageBox.question(self, "确认", 
                                    "即将清理 {} 个项目。此操作不可逆,是否继续?".format(len(selected_items)),
                                    QMessageBox.Yes | QMessageBox.No)
        
        if reply == QMessageBox.Yes:
            self.clean_btn.setEnabled(False)
            self.cleaner_thread = CleanerThread(selected_items)
            self.cleaner_thread.progress_signal.connect(self.update_progress)
            self.cleaner_thread.finished_signal.connect(self.cleaning_finished)
            self.cleaner_thread.start()
    
    def update_progress(self, value, message):
        """更新进度条和状态标签"""
        self.progress_bar.setValue(value)
        self.status_label.setText(message)
    
    def cleaning_finished(self, success, message):
        """清理完成后的处理"""
        self.clean_btn.setEnabled(True)
        self.status_label.setText(message)
        QMessageBox.information(self, "完成", message)
        
        # 重新扫描系统
        self.scan_system()
    
    def export_list(self):
        """导出清理列表到文件"""
        selected_items = self.get_selected_items()
        if not selected_items:
            QMessageBox.warning(self, "警告", "没有选中的项目可导出")
            return
        
        file_path, _ = QFileDialog.getSaveFileName(self, "导出列表", "", "文本文件 (*.txt)")
        if file_path:
            try:
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write("360安全卫士残留清理列表\n")
                    f.write("=" * 50 + "\n\n")
                    
                    for item_type, path in selected_items:
                        f.write(f"{item_type}: {path}\n")
                
                QMessageBox.information(self, "成功", "列表已导出到: {}".format(file_path))
            except Exception as e:
                QMessageBox.critical(self, "错误", "导出失败: {}".format(str(e)))

if __name__ == "__main__":
    # 检查管理员权限
    if os.name == 'nt':
        try:
            import ctypes
            if ctypes.windll.shell32.IsUserAnAdmin() == 0:
                QMessageBox.critical(None, "错误", "此程序需要管理员权限才能运行")
                sys.exit(1)
        except:
            pass
    
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

通义千问

import os
import shutil
import winreg
import logging
from datetime import datetime
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout, QPushButton,
    QCheckBox, QGroupBox, QLabel, QScrollArea, QFrame, QMessageBox,
    QTextEdit, QDialog, QSizePolicy
)
from PyQt5.QtCore import Qt, pyqtSignal
from PyQt5.QtGui import QFont

# ================== 配置 ==================
LOG_FILE = "360_cleaner_log.txt"
logging.basicConfig(
    filename=LOG_FILE,
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    encoding="utf-8"
)

# 当前用户名
USERNAME = os.getlogin()

# 要清理的目录
DIRECTORIES = [
    r"C:\360SANDBOX",
    r"C:\$360Section",
    r"C:\Program Files (x86)\360",
    r"C:\ProgramData\360safe",
    r"C:\ProgramData\360SD",
    fr"C:\Users\{USERNAME}\AppData\LocalLow\360WD",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360DesktopLite",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360Login",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360Quarant",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360Safe",
]

# 注册表项 (hkey, subkey, 描述)
REGISTRY_ITEMS = [
    (winreg.HKEY_CLASSES_ROOT, r"*\\shellex\\ContextMenuHandlers\\Safe360Ext", "右键菜单 - 扫描"),
    (winreg.HKEY_CLASSES_ROOT, r"Folder\\ShellEx\\ContextMenuHandlers\\Safe360Ext", "右键菜单 - 文件夹扫描"),
    (winreg.HKEY_CLASSES_ROOT, r"lnkfile\\shellex\\ContextMenuHandlers\\Safe360Ext", "右键菜单 - 快捷方式扫描"),
    (winreg.HKEY_CLASSES_ROOT, r"qsdis\\shell\\open\\command", "360下载协议"),
    (winreg.HKEY_CLASSES_ROOT, r"qsoftmgr\\shell\\open\\command", "360软件管家协议"),
    (winreg.HKEY_CLASSES_ROOT, r"softmanager360\\Shell\\Open\\Command", "软件管家"),
    (winreg.HKEY_CURRENT_USER, r"Software\\360safe", "用户设置 - 360安全卫士"),
    (winreg.HKEY_CURRENT_USER, r"Software\\360se6", "用户设置 - 360浏览器"),
    (winreg.HKEY_CURRENT_USER, r"Software\\360SoftMgr", "用户设置 - 软件管家"),
    (winreg.HKEY_CURRENT_USER, r"Software\\LiveUpdate360", "用户设置 - 更新"),
    (winreg.HKEY_CURRENT_USER, r"Software\\MozillaPlugins\\@360.cn/360SoftMgrPlugin", "浏览器插件"),
    (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Classes\\360SafeLive.Update", "系统更新组件"),
    (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Classes\\360SafeLive.Update.2", "系统更新组件2"),
    (winreg.HKEY_USERS, r"360SandBox", "沙箱用户配置"),
    (winreg.HKEY_USERS, r"360SPDM", "360驱动管理用户"),
]

# ================== 工具函数 ==================
def is_path_exists(path):
    return os.path.exists(path) or os.path.isdir(path)

def is_reg_key_exists(hkey, subkey):
    try:
        reg = winreg.OpenKey(hkey, subkey, 0, winreg.KEY_READ)
        winreg.CloseKey(reg)
        return True
    except:
        return False

def backup_registry_key(hkey, subkey, backup_dir="reg_backup"):
    os.makedirs(backup_dir, exist_ok=True)
    safe_subkey = subkey.replace("\\\\", "_").replace("\\", "_")
    backup_path = os.path.join(backup_dir, f"{safe_subkey}.reg")
    try:
        os.system(f'reg export "{hkey_name(hkey)}\\{subkey}" "{backup_path}" >nul 2>&1')
        logging.info(f"已备份注册表: {subkey} -> {backup_path}")
        return backup_path
    except Exception as e:
        logging.error(f"备份失败 {subkey}: {e}")
        return None

def hkey_name(hkey):
    return {
        winreg.HKEY_CLASSES_ROOT: "HKEY_CLASSES_ROOT",
        winreg.HKEY_CURRENT_USER: "HKEY_CURRENT_USER",
        winreg.HKEY_LOCAL_MACHINE: "HKEY_LOCAL_MACHINE",
        winreg.HKEY_USERS: "HKEY_USERS"
    }.get(hkey, str(hkey))

def delete_directory(path):
    try:
        shutil.rmtree(path)
        logging.info(f"[✓] 删除目录: {path}")
        return True, "删除成功"
    except Exception as e:
        msg = f"删除失败: {e}"
        logging.error(f"[✗] 删除失败 {path}: {e}")
        return False, msg

def delete_registry_key(hkey, subkey):
    try:
        backup_registry_key(hkey, subkey)
        winreg.DeleteKey(hkey, subkey)
        logging.info(f"[✓] 删除注册表: {hkey_name(hkey)}\\{subkey}")
        return True, "删除成功"
    except Exception as e:
        msg = f"删除失败: {e}"
        logging.error(f"[✗] 删除失败 {subkey}: {e}")
        return False, msg

# ================== 日志查看对话框 ==================
class LogDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("清理日志")
        self.resize(800, 500)
        layout = QVBoxLayout()

        self.text_edit = QTextEdit()
        self.text_edit.setReadOnly(True)
        self.text_edit.setFont(QFont("Consolas", 9))

        if os.path.exists(LOG_FILE):
            with open(LOG_FILE, 'r', encoding='utf-8') as f:
                self.text_edit.setText(f.read())
        else:
            self.text_edit.setText("日志文件不存在。")

        layout.addWidget(self.text_edit)
        self.setLayout(layout)

# ================== 主窗口 ==================
class CleanerApp(QWidget):
    def __init__(self):
        super().__init__()
        self.file_checks = {}
        self.reg_checks = {}
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("360残留清理助手 (PyQt5版) v1.0")
        self.resize(900, 700)
        self.setFont(QFont("微软雅黑", 9))

        # 标题
        title = QLabel("360安全卫士残留清理工具")
        title.setFont(QFont("微软雅黑", 16, QFont.Bold))
        title.setAlignment(Qt.AlignCenter)
        title.setStyleSheet("color: darkblue; margin: 10px;")

        desc = QLabel("请先扫描,然后勾选要删除的项目。")
        desc.setAlignment(Qt.AlignCenter)
        desc.setStyleSheet("color: gray; font-size: 12px;")

        # 按钮行
        btn_layout = QHBoxLayout()
        self.btn_scan = QPushButton("🔍 扫描残留")
        self.btn_clean = QPushButton("🗑️ 开始清理")
        self.btn_log = QPushButton("📄 查看日志")

        self.btn_scan.clicked.connect(self.scan)
        self.btn_clean.clicked.connect(self.clean)
        self.btn_log.clicked.connect(self.view_log)

        for btn in [self.btn_scan, self.btn_clean, self.btn_log]:
            btn.setMinimumHeight(35)
            btn.setFont(QFont("微软雅黑", 10))

        btn_layout.addWidget(self.btn_scan)
        btn_layout.addWidget(self.btn_clean)
        btn_layout.addWidget(self.btn_log)

        # 状态栏
        self.status_label = QLabel("就绪")
        self.status_label.setStyleSheet("color: blue; padding: 5px;")

        # 分割线
        line = QFrame()
        line.setFrameShape(QFrame.HLine)
        line.setFrameShadow(QFrame.Sunken)

        # 主内容区(滚动)
        scroll = QScrollArea()
        scroll.setWidgetResizable(True)
        scroll_content = QWidget()
        scroll_layout = QVBoxLayout(scroll_content)

        # 文件区域
        file_group = QGroupBox("📁 文件与目录残留")
        file_layout = QVBoxLayout()
        self.file_container = QWidget()
        self.file_container.setLayout(QVBoxLayout())
        file_layout.addWidget(self.file_container)

        btn_file = QHBoxLayout()
        self.btn_file_select_all = QPushButton("✅ 全选")
        self.btn_file_unselect = QPushButton("❌ 取消全选")
        self.btn_file_select_all.clicked.connect(lambda: self.select_all(self.file_checks, True))
        self.btn_file_unselect.clicked.connect(lambda: self.select_all(self.file_checks, False))
        btn_file.addWidget(self.btn_file_select_all)
        btn_file.addWidget(self.btn_file_unselect)
        btn_file.addStretch()

        file_layout.addLayout(btn_file)
        file_group.setLayout(file_layout)

        # 注册表区域
        reg_group = QGroupBox("🪟 注册表残留")
        reg_layout = QVBoxLayout()
        self.reg_container = QWidget()
        self.reg_container.setLayout(QVBoxLayout())
        reg_layout.addWidget(self.reg_container)

        btn_reg = QHBoxLayout()
        self.btn_reg_select_all = QPushButton("✅ 全选")
        self.btn_reg_unselect = QPushButton("❌ 取消全选")
        self.btn_reg_select_all.clicked.connect(lambda: self.select_all(self.reg_checks, True))
        self.btn_reg_unselect.clicked.connect(lambda: self.select_all(self.reg_checks, False))
        btn_reg.addWidget(self.btn_reg_select_all)
        btn_reg.addWidget(self.btn_reg_unselect)
        btn_reg.addStretch()

        reg_layout.addLayout(btn_reg)
        reg_group.setLayout(reg_layout)

        # 添加到主布局
        scroll_layout.addWidget(file_group)
        scroll_layout.addWidget(reg_group)
        scroll_layout.addStretch()
        scroll.setWidget(scroll_content)

        # 主布局
        layout = QVBoxLayout()
        layout.addWidget(title)
        layout.addWidget(desc)
        layout.addLayout(btn_layout)
        layout.addWidget(line)
        layout.addWidget(scroll)
        layout.addWidget(self.status_label)
        self.setLayout(layout)

        # 初始化状态
        self.btn_clean.setEnabled(False)
        self.btn_log.setEnabled(True)

    def select_all(self, check_dict, selected):
        for checkbox in check_dict.values():
            checkbox.setChecked(selected)
        self.status_label.setText(f"已{'全选' if selected else '取消全选'}")

    def scan(self):
        # 清空
        for i in reversed(range(self.file_container.layout().count())):
            widget = self.file_container.layout().takeAt(i).widget()
            if widget:
                widget.deleteLater()
        for i in reversed(range(self.reg_container.layout().count())):
            widget = self.reg_container.layout().takeAt(i).widget()
            if widget:
                widget.deleteLater()

        self.file_checks.clear()
        self.reg_checks.clear()

        # 扫描文件
        found_file = False
        for path in DIRECTORIES:
            if is_path_exists(path):
                cb = QCheckBox(path)
                self.file_container.layout().addWidget(cb)
                self.file_checks[path] = cb
                found_file = True

        if not found_file:
            no_label = QLabel("未发现残留目录")
            no_label.setStyleSheet("color: green;")
            self.file_container.layout().addWidget(no_label)

        # 扫描注册表
        found_reg = False
        for hkey, subkey, desc in REGISTRY_ITEMS:
            if is_reg_key_exists(hkey, subkey):
                cb = QCheckBox(f"{hkey_name(hkey)}\\{subkey}")
                desc_label = QLabel(f"  └─ [{desc}]")
                desc_label.setStyleSheet("color: gray; font-size: 11px; margin-left: 20px;")

                container = QWidget()
                v = QVBoxLayout()
                v.setContentsMargins(0, 0, 0, 0)
                v.addWidget(cb)
                v.addWidget(desc_label)
                container.setLayout(v)

                self.reg_container.layout().addWidget(container)
                self.reg_checks[(hkey, subkey)] = (cb, desc)
                found_reg = True

        if not found_reg:
            no_label = QLabel("未发现残留注册表项")
            no_label.setStyleSheet("color: green;")
            self.reg_container.layout().addWidget(no_label)

        total_files = len([c for c in self.file_checks.values() if isinstance(c, QCheckBox)])
        total_regs = len([c for c in self.reg_checks.values()])

        self.status_label.setText(f"扫描完成,发现文件残留 {total_files} 项,注册表残留 {total_regs} 项。")
        self.btn_clean.setEnabled(total_files > 0 or total_regs > 0)

    def clean(self):
        selected_files = [path for path, cb in self.file_checks.items() if cb.isChecked()]
        selected_regs = [key for key, (cb, _) in self.reg_checks.items() if cb.isChecked()]

        if not selected_files and not selected_regs:
            QMessageBox.information(self, "提示", "没有勾选任何项目。")
            return

        reply = QMessageBox.question(
            self, "确认",
            f"即将删除 {len(selected_files)} 个目录和 {len(selected_regs)} 个注册表项,是否继续?",
            QMessageBox.Yes | QMessageBox.No
        )
        if reply != QMessageBox.Yes:
            return

        success = 0
        fail = 0

        # 删除文件
        for path in selected_files:
            ok, _ = delete_directory(path)
            success += ok
            fail += not ok

        # 删除注册表
        for (hkey, subkey), (cb, desc) in self.reg_checks.items():
            if cb.isChecked():
                ok, _ = delete_registry_key(hkey, subkey)
                success += ok
                fail += not ok

        QMessageBox.information(self, "完成", f"清理完成!\n成功: {success}\n失败: {fail}\n日志已保存。")
        self.status_label.setText(f"清理完成,成功 {success},失败 {fail}")

    def view_log(self):
        dialog = LogDialog(self)
        dialog.exec_()

# ================== 启动入口 ==================
def main():
    import ctypes
    if not ctypes.windll.shell32.IsUserAnAdmin():
        QMessageBox.critical(None, "权限错误", "请以管理员身份运行此程序!")
        return

    app = QApplication([])
    window = CleanerApp()
    window.show()
    app.exec_()

if __name__ == "__main__":
    main()

 

import os
import shutil
import winreg
import logging
from datetime import datetime
import tkinter as tk
from tkinter import ttk, messagebox, scrolledtext

# ================== 配置 ==================
LOG_FILE = "360_cleaner_log.txt"
logging.basicConfig(
    filename=LOG_FILE,
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    encoding="utf-8"
)

USERNAME = os.getlogin()

DIRECTORIES = [
    r"C:\360SANDBOX",
    r"C:\$360Section",
    r"C:\Program Files (x86)\360",
    r"C:\ProgramData\360safe",
    r"C:\ProgramData\360SD",
    fr"C:\Users\{USERNAME}\AppData\LocalLow\360WD",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360DesktopLite",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360Login",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360Quarant",
    fr"C:\Users\{USERNAME}\AppData\Roaming\360Safe",
]

REGISTRY_ITEMS = [
    (winreg.HKEY_CLASSES_ROOT, r"*\\shellex\\ContextMenuHandlers\\Safe360Ext", "右键菜单 - 扫描"),
    (winreg.HKEY_CLASSES_ROOT, r"Folder\\ShellEx\\ContextMenuHandlers\\Safe360Ext", "右键菜单 - 文件夹扫描"),
    (winreg.HKEY_CLASSES_ROOT, r"lnkfile\\shellex\\ContextMenuHandlers\\Safe360Ext", "右键菜单 - 快捷方式扫描"),
    (winreg.HKEY_CLASSES_ROOT, r"qsdis\\shell\\open\\command", "360下载协议"),
    (winreg.HKEY_CLASSES_ROOT, r"qsoftmgr\\shell\\open\\command", "360软件管家协议"),
    (winreg.HKEY_CLASSES_ROOT, r"softmanager360\\Shell\\Open\\Command", "软件管家"),
    (winreg.HKEY_CURRENT_USER, r"Software\\360safe", "用户设置 - 360安全卫士"),
    (winreg.HKEY_CURRENT_USER, r"Software\\360se6", "用户设置 - 360浏览器"),
    (winreg.HKEY_CURRENT_USER, r"Software\\360SoftMgr", "用户设置 - 软件管家"),
    (winreg.HKEY_CURRENT_USER, r"Software\\LiveUpdate360", "用户设置 - 更新"),
    (winreg.HKEY_CURRENT_USER, r"Software\\MozillaPlugins\\@360.cn/360SoftMgrPlugin", "浏览器插件"),
    (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Classes\\360SafeLive.Update", "系统更新组件"),
    (winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\\Classes\\360SafeLive.Update.2", "系统更新组件2"),
    (winreg.HKEY_USERS, r"360SandBox", "沙箱用户配置"),
    (winreg.HKEY_USERS, r"360SPDM", "360驱动管理用户"),
]

def is_path_exists(path):
    return os.path.exists(path) or os.path.isdir(path)

def is_reg_key_exists(hkey, subkey):
    try:
        reg = winreg.OpenKey(hkey, subkey, 0, winreg.KEY_READ)
        winreg.CloseKey(reg)
        return True
    except:
        return False

def backup_registry_key(hkey, subkey, backup_dir="reg_backup"):
    os.makedirs(backup_dir, exist_ok=True)
    backup_path = os.path.join(backup_dir, f"{subkey.replace('\\\\', '_')}.reg")
    try:
        os.system(f'reg export "{hkey_name(hkey)}\\{subkey}" "{backup_path}" >nul 2>&1')
        return backup_path
    except Exception as e:
        logging.error(f"备份失败 {subkey}: {e}")
        return None

def hkey_name(hkey):
    return {
        winreg.HKEY_CLASSES_ROOT: "HKEY_CLASSES_ROOT",
        winreg.HKEY_CURRENT_USER: "HKEY_CURRENT_USER",
        winreg.HKEY_LOCAL_MACHINE: "HKEY_LOCAL_MACHINE",
        winreg.HKEY_USERS: "HKEY_USERS"
    }.get(hkey, str(hkey))

def delete_directory(path):
    try:
        shutil.rmtree(path)
        logging.info(f"[✓] 删除目录: {path}")
        return True, "删除成功"
    except Exception as e:
        msg = f"删除失败: {e}"
        logging.error(f"[✗] 删除失败 {path}: {e}")
        return False, msg

def delete_registry_key(hkey, subkey):
    try:
        backup = backup_registry_key(hkey, subkey)
        if backup:
            logging.info(f"已备份: {subkey} -> {backup}")
        winreg.DeleteKey(hkey, subkey)
        logging.info(f"[✓] 删除注册表: {hkey_name(hkey)}\\{subkey}")
        return True, "删除成功"
    except Exception as e:
        msg = f"删除失败: {e}"
        logging.error(f"[✗] 删除失败 {subkey}: {e}")
        return False, msg

# ================== GUI 增强版 ==================
class CleanerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("360残留清理助手 v1.1")
        self.root.geometry("950x750")
        self.root.resizable(False, False)

        self.file_vars = {}
        self.reg_vars = {}

        self.create_widgets()

    def create_widgets(self):
        title = tk.Label(self.root, text="360安全卫士残留清理工具", font=("微软雅黑", 16, "bold"), fg="darkblue")
        title.pack(pady=10)

        desc = tk.Label(self.root, text="请先扫描,然后勾选要删除的项目,支持全选/取消。", fg="gray")
        desc.pack()

        btn_frame = tk.Frame(self.root)
        btn_frame.pack(pady=10)

        tk.Button(btn_frame, text="🔍 扫描残留", command=self.scan, width=15, bg="#4CAF50", fg="white").grid(row=0, column=0, padx=5)
        tk.Button(btn_frame, text="🗑️ 开始清理", command=self.clean, width=15, bg="#f44336", fg="white").grid(row=0, column=1, padx=5)
        tk.Button(btn_frame, text="📄 查看日志", command=self.view_log, width=15).grid(row=0, column=2, padx=5)

        ttk.Separator(self.root, orient='horizontal').pack(fill='x', padx=20, pady=10)

        # 文件区域
        file_label = tk.Label(self.root, text="📁 文件与目录残留", font=("微软雅黑", 12, "bold"))
        file_label.pack(anchor='w', padx=20)

        file_outer = tk.Frame(self.root, relief="groove", bd=1)
        file_outer.pack(fill='x', padx=20, pady=5)

        self.file_frame = tk.Frame(file_outer)
        self.file_frame.pack(pady=5)

        file_btn_frame = tk.Frame(file_outer)
        file_btn_frame.pack(anchor='w', padx=10, pady=5)
        tk.Button(file_btn_frame, text="✅ 全选", command=lambda: self.select_all(self.file_vars, True), width=10).pack(side='left')
        tk.Button(file_btn_frame, text="❌ 取消全选", command=lambda: self.select_all(self.file_vars, False), width=10).pack(side='left')

        # 注册表区域
        reg_label = tk.Label(self.root, text="🪟 注册表残留", font=("微软雅黑", 12, "bold"))
        reg_label.pack(anchor='w', padx=20, pady=(20,0))

        reg_outer = tk.Frame(self.root, relief="groove", bd=1)
        reg_outer.pack(fill='x', padx=20, pady=5)

        self.reg_frame = tk.Frame(reg_outer)
        self.reg_frame.pack(pady=5)

        reg_btn_frame = tk.Frame(reg_outer)
        reg_btn_frame.pack(anchor='w', padx=10, pady=5)
        tk.Button(reg_btn_frame, text="✅ 全选", command=lambda: self.select_all(self.reg_vars, True), width=10).pack(side='left')
        tk.Button(reg_btn_frame, text="❌ 取消全选", command=lambda: self.select_all(self.reg_vars, False), width=10).pack(side='left')

        self.status = tk.Label(self.root, text="就绪", fg="blue", anchor='w')
        self.status.pack(side='bottom', fill='x', padx=10, pady=5)

    def select_all(self, var_dict, select=True):
        for var in var_dict.values():
            if isinstance(var, tuple):  # 注册表
                var[0].set(select)
            else:  # 文件
                var.set(select)
        self.status.config(text=f"已{'全选' if select else '取消全选'}")

    def scan(self):
        for widget in self.file_frame.winfo_children():
            widget.destroy()
        for widget in self.reg_frame.winfo_children():
            widget.destroy()

        self.file_vars.clear()
        self.reg_vars.clear()

        # 扫描文件
        for i, path in enumerate(DIRECTORIES):
            if is_path_exists(path):
                var = tk.BooleanVar()
                cb = tk.Checkbutton(self.file_frame, text=path, variable=var, font=("Consolas", 9))
                cb.grid(row=i, sticky='w', pady=1)
                self.file_vars[path] = var

        if not self.file_vars:
            tk.Label(self.file_frame, text="未发现残留目录", fg="green").grid(row=0, sticky='w')

        # 扫描注册表
        for i, (hkey, subkey, desc) in enumerate(REGISTRY_ITEMS):
            if is_reg_key_exists(hkey, subkey):
                var = tk.BooleanVar()
                frame = tk.Frame(self.reg_frame)
                frame.grid(row=i, sticky='w', pady=1)
                tk.Checkbutton(frame, text=f"{hkey_name(hkey)}\\{subkey}", variable=var, font=("Consolas", 9)).pack(anchor='w')
                tk.Label(frame, text=f"[{desc}]", fg="gray", font=("微软雅黑", 8)).pack(anchor='w', padx=20)
                self.reg_vars[(hkey, subkey)] = (var, desc)

        if not self.reg_vars:
            tk.Label(self.reg_frame, text="未发现残留注册表项", fg="green").pack(anchor='w')

        self.status.config(text=f"扫描完成,文件残留 {len(self.file_vars)} 项,注册表残留 {len(self.reg_vars)} 项。")

    def clean(self):
        if not any(v.get() for v in self.file_vars.values()) and not any(v[0].get() for v in self.reg_vars.values()):
            if messagebox.askyesno("提示", "没有勾选任何项目,是否扫描查看?"):
                self.scan()
            return

        if not messagebox.askyesno("确认", "即将删除选中的项目,是否继续?\n建议先备份重要数据。"):
            return

        success = 0
        fail = 0

        for path, var in self.file_vars.items():
            if var.get():
                ok, _ = delete_directory(path)
                success += ok
                fail += not ok

        for (hkey, subkey), (var, desc) in self.reg_vars.items():
            if var.get():
                ok, _ = delete_registry_key(hkey, subkey)
                success += ok
                fail += not ok

        messagebox.showinfo("完成", f"清理完成!\n成功: {success} 项\n失败: {fail} 项\n日志已保存")
        self.status.config(text=f"清理完成,成功 {success},失败 {fail}")

    def view_log(self):
        log_window = tk.Toplevel(self.root)
        log_window.title("清理日志")
        log_window.geometry("800x500")
        text = scrolledtext.ScrolledText(log_window, font=("Consolas", 9))
        text.pack(fill='both', expand=True)
        if os.path.exists(LOG_FILE):
            with open(LOG_FILE, 'r', encoding='utf-8') as f:
                text.insert('1.0', f.read())
        else:
            text.insert('1.0', "日志文件不存在。")

# ================== 主程序 ==================
if __name__ == "__main__":
    import ctypes
    if not ctypes.windll.shell32.IsUserAnAdmin():
        messagebox.showerror("权限", "请以管理员身份运行!")
        exit()
    root = tk.Tk()
    app = CleanerApp(root)
    root.mainloop()

Kimi

# -*- coding: utf-8 -*-
# 360SweepPro  增强版(一键扫描+一键清理+备份+驱动重启删)
import os, sys, shutil, winreg, tempfile, subprocess, threading, json, time, pathlib
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import ctypes
from ctypes import wintypes

MOVEFILE_DELAY_UNTIL_REBOOT = 4
kernel32 = ctypes.windll.kernel32
kernel32.MoveFileExW.argtypes = [wintypes.LPCWSTR, wintypes.LPCWSTR, wintypes.DWORD]
kernel32.MoveFileExW.restype = wintypes.BOOL

ICON = 'res/360SweepPro.ico'
LOGO = '360SweepPro'
VERSION = 'v1.0'

# ---------- 工具 ----------
def log(msg):
    with open('360SweepPro.log', 'a', encoding='utf-8') as f:
        f.write(f'{time.strftime("%Y-%m-%d %H:%M:%S")}  {msg}\n')

def backup_reg(keyPath):
    """导出一个 .reg 备份"""
    fname = pathlib.Path(tempfile.gettempdir()) / f'360SweepPro_backup_{int(time.time())}.reg'
    subprocess.run(['reg', 'export', keyPath, str(fname), '/y'], check=False)
    return str(fname)

def del_reg(keyPath):
    try:
        winreg.DeleteKey(winreg.HKEY_CLASSES_ROOT, keyPath[len('HKEY_CLASSES_ROOT\\'):])
        return True
    except:
        return False

def del_file(path):
    try:
        if os.path.isdir(path):
            shutil.rmtree(path)
        else:
            os.remove(path)
        return True
    except PermissionError:
        # 驱动被占用 → 注册重启删除
        ok = kernel32.MoveFileExW(path, None, MOVEFILE_DELAY_UNTIL_REBOOT)
        return bool(ok)
    except:
        return False

# ---------- 扫描线程 ----------
class Scanner(QThread):
    found = pyqtSignal(str, str)   # path, type
    done  = pyqtSignal()

    def run(self):
        # 1. 目录
        dirs = [os.path.expandvars(p) for p in [
            r'%ProgramData%\360safe', r'%ProgramData%\360SD',
            r'C:\360SANDBOX', r'C:\$360Section',
            r'%USERPROFILE%\AppData\Roaming\360Safe',
            r'%USERPROFILE%\AppData\Roaming\360DesktopLite',
            r'%USERPROFILE%\AppData\Roaming\360Login',
            r'%USERPROFILE%\AppData\Roaming\360Quarant',
            r'%USERPROFILE%\AppData\LocalLow\360WD'
        ]]
        for d in dirs:
            if os.path.exists(d):
                self.found.emit(d, '目录')

        # 2. 驱动
        for drv in pathlib.Path(r'C:\Windows\System32\drivers').glob('360*.sys'):
            self.found.emit(str(drv), '驱动')

        # 3. 注册表(递归 GUID)
        self.scan_reg()
        self.done.emit()

    def scan_reg(self):
        roots = [
            (winreg.HKEY_CLASSES_ROOT, r'CLSID'),
            (winreg.HKEY_CLASSES_ROOT, r'*\shellex\ContextMenuHandlers\Safe360Ext'),
            (winreg.HKEY_CURRENT_USER, r'Software\360safe'),
            (winreg.HKEY_CURRENT_USER, r'Software\360se6'),
            (winreg.HKEY_USERS, r'360SandBox'),
            (winreg.HKEY_USERS, r'360SPDM')
        ]
        for root, sub in roots:
            try:
                key = winreg.OpenKey(root, sub)
                winreg.CloseKey(key)
                path = 'HKEY_CLASSES_ROOT\\' + sub if root == winreg.HKEY_CLASSES_ROOT else \
                       'HKEY_CURRENT_USER\\' + sub if root == winreg.HKEY_CURRENT_USER else \
                       'HKEY_USERS\\' + sub
                self.found.emit(path, '注册表')
            except:
                pass

# ---------- 主界面 ----------
class MainWin(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle(f'{LOGO}  {VERSION}')
        self.setFixedSize(800, 600)
        self.setWindowIcon(QIcon(ICON))
        self._initUI()
        self.scanner = Scanner(self)
        self.scanner.found.connect(self.add_row)
        self.scanner.done.connect(self.scan_done)
        self.data = []   # [(path, type, chk), ...]

    def _initUI(self):
        central = QWidget()
        self.setCentralWidget(central)
        v = QVBoxLayout(central)

        self.bar = QProgressBar()
        self.bar.setRange(0, 0)
        self.bar.hide()
        v.addWidget(self.bar)

        self.table = QTableWidget(0, 4)
        self.table.setHorizontalHeaderLabels(['', '路径', '类型', '结果'])
        self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
        self.table.setSelectionBehavior(QAbstractItemView.SelectRows)

        h = QHBoxLayout()
        self.oneScan = QPushButton('一键扫描')
        self.oneClean= QPushButton('一键清理')
        self.quitBtn = QPushButton('退出')
        h.addWidget(self.oneScan)
        h.addWidget(self.oneClean)
        h.addWidget(self.quitBtn)
        self.oneClean.setEnabled(False)

        v.addWidget(self.table)
        v.addLayout(h)

        self.oneScan.clicked.connect(self.start_scan)
        self.oneClean.clicked.connect(self.one_key_clean)
        self.quitBtn.clicked.connect(self.close)

    def start_scan(self):
        self.data.clear()
        self.table.setRowCount(0)
        self.bar.show()
        self.oneScan.setEnabled(False)
        self.scanner.start()

    def add_row(self, path, typ):
        row = self.table.rowCount()
        self.table.insertRow(row)
        chk = QTableWidgetItem()
        chk.setCheckState(Qt.Checked)
        self.table.setItem(row, 0, chk)
        self.table.setItem(row, 1, QTableWidgetItem(path))
        self.table.setItem(row, 2, QTableWidgetItem(typ))
        self.table.setItem(row, 3, QTableWidgetItem(''))
        self.data.append((path, typ, chk))

    def scan_done(self):
        self.bar.hide()
        self.oneScan.setEnabled(True)
        self.oneClean.setEnabled(True)
        QMessageBox.information(self, '提示', f'扫描完成,共 {len(self.data)} 条残留')

    def one_key_clean(self):
        sel = [(p, t) for p, t, chk in self.data if chk.checkState() == Qt.Checked]
        if not sel:
            QMessageBox.information(self, '提示', '请先勾选要清理的项')
            return
        ans = QMessageBox.question(self, '确认', f'将清理 {len(sel)} 条记录,并自动备份注册表,继续?')
        if ans != QMessageBox.Yes:
            return
        ok_cnt = 0
        for path, typ in sel:
            bak = ''
            if typ == '注册表':
                bak = backup_reg(path)
                ok = del_reg(path)
            else:
                ok = del_file(path)
            ok_cnt += ok
            # 回写结果
            for row in range(self.table.rowCount()):
                if self.table.item(row, 1).text() == path:
                    self.table.setItem(row, 3, QTableWidgetItem('已删除' if ok else '失败'))
        log(f'一键清理完成 成功={ok_cnt} 总数={len(sel)}')
        QMessageBox.information(self, '完成', f'清理完毕!成功 {ok_cnt}/{len(sel)}\n注册表备份保存在 temp 目录')

if __name__ == '__main__':
    app = QApplication(sys.argv)
    w = MainWin()
    w.show()
    sys.exit(app.exec_())

打包成exe可执行程序的命令,运行需要右键 “以管理员身份运行”

pyinstaller --onefile --windowed 360_cleaner.py

 


sicnature ---------------------------------------------------------------------
I P 地 址: 216.73.216.187
区 域 位 置: 美国加利福尼亚洛杉矶
系 统 信 息: 美国
Original content, please indicate the source:
同福客栈论坛 | 蟒蛇科普海南乡情论坛 | JiaYu Blog
sicnature ---------------------------------------------------------------------
Welcome to reprint. Please indicate the source https://www.myzhenai.com/post/4810.html

没有评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注