Navicat 完整清理脚本
根据Navicat软件卸载,最干净的方法_Python脚本
import os
import sys
import json
import shutil
import psutil
import winreg
import ctypes
import socket
import datetime
import subprocess
import glob
import tempfile
from pathlib import Pathclass Logger:def __init__(self, logfile):self.logfile = logfileself.use_stdout = sys.stdout.isatty()def log(self, msg):timestamp = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')line = f"{timestamp} - {msg}"with open(self.logfile, 'a', encoding='utf-8') as f:f.write(line + '\n')if self.use_stdout:print(msg)class NavicatCleaner:def __init__(self, thorough=True):self.thorough = thoroughself.hostname = socket.gethostname()self.username = os.getenv('USERNAME')self.current_pid = os.getpid()self.current_exe = os.path.abspath(getattr(sys, 'frozen', False) and sys.executable or sys.argv[0])self.report = {'hostname': self.hostname,'username': self.username,'scan_time': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'),'navicat_found': False,'items_removed': [],'errors': []}self.logfile = f"{self.hostname}_complete_clean.log"self.logger = Logger(self.logfile)self.logger.log(f"当前进程PID: {self.current_pid}")self.logger.log(f"当前程序路径: {self.current_exe}")def is_admin(self):try:return ctypes.windll.shell32.IsUserAnAdmin()except:return Falsedef run_as_admin(self):if not self.is_admin():self.logger.log('需要管理员权限,正在提升权限...')ctypes.windll.shell32.ShellExecuteW(None, 'runas', sys.executable, ' '.join(sys.argv), None, 1)sys.exit()def kill_navicat_processes(self):self.logger.log('[1/8] 终止Navicat进程...')killed = []for proc in psutil.process_iter(['pid', 'name', 'exe']):try:if proc.info['pid'] == self.current_pid:self.logger.log(f" ⊙ 跳过当前进程: PID {self.current_pid}")continuename = proc.info['name'].lower()exe_path = proc.info.get('exe', '')if exe_path and os.path.abspath(exe_path) == self.current_exe:self.logger.log(f" ⊙ 跳过当前程序: {exe_path}")continueif 'navicat' in name or (exe_path and 'navicat' in exe_path.lower()):proc.terminate()killed.append(name)self.logger.log(f" ✓ 已终止: {name} (PID: {proc.info['pid']})")if exe_path and os.path.exists(exe_path):parent_dir = os.path.dirname(exe_path)self.report['items_removed'].append(f"程序目录: {parent_dir}")except (psutil.NoSuchProcess, psutil.AccessDenied):passif killed:self.report['navicat_found'] = Truedef clean_program_files(self):self.logger.log('[2/8] 清理程序文件...')paths = ['C:\\Program Files\\PremiumSoft','C:\\Program Files (x86)\\PremiumSoft','C:\\Program Files\\Navicat','C:\\Program Files (x86)\\Navicat']for drive in ('C:', 'D:', 'E:', 'F:'):if os.path.exists(f"{drive}\\"):paths.extend([f"{drive}\\PremiumSoft",f"{drive}\\Navicat",f"{drive}\\Tools\\Navicat",f"{drive}\\Software\\Navicat",f"{drive}\\Program Files\\PremiumSoft",f"{drive}\\Program Files (x86)\\PremiumSoft"])current_dir = os.path.dirname(self.current_exe)for path in paths:if not os.path.exists(path):continueif os.path.abspath(path) == os.path.abspath(current_dir):self.logger.log(f" ⊙ 跳过当前程序目录: {path}")continuetry:shutil.rmtree(path, ignore_errors=True)self.logger.log(f" ✓ 已删除: {path}")self.report['items_removed'].append(f"程序文件: {path}")self.report['navicat_found'] = Trueexcept Exception as e:self.report['errors'].append(f"无法删除 {path}: {e}")def clean_user_data(self):self.logger.log('[3/8] 清理用户数据...')user_paths = [os.path.expandvars('%APPDATA%\\PremiumSoft'),os.path.expandvars('%APPDATA%\\Navicat'),os.path.expandvars('%LOCALAPPDATA%\\PremiumSoft'),os.path.expandvars('%LOCALAPPDATA%\\Navicat'),os.path.expandvars('%LOCALAPPDATA%\\Temp\\NavicatService'),os.path.expandvars('%TEMP%\\NavicatService'),os.path.expandvars('%TEMP%\\Navicat*'),os.path.expandvars('%USERPROFILE%\\Documents\\Navicat'),os.path.expandvars('%USERPROFILE%\\Documents\\PremiumSoft'),os.path.expandvars('%USERPROFILE%\\Desktop\\Navicat*'),os.path.expandvars('%USERPROFILE%\\Desktop\\PremiumSoft*'),os.path.expandvars('%USERPROFILE%\\Downloads\\navicat*'),os.path.expandvars('%USERPROFILE%\\Downloads\\PremiumSoft*'),'C:\\ProgramData\\PremiumSoft','C:\\ProgramData\\Navicat']current_dir = os.path.dirname(self.current_exe)for pattern in user_paths:for path in glob.glob(pattern):if not os.path.exists(path):continueif os.path.abspath(path) == os.path.abspath(current_dir):self.logger.log(f" ⊙ 跳过当前程序目录: {path}")continuetry:if os.path.isdir(path):shutil.rmtree(path, ignore_errors=True)else:os.remove(path)self.logger.log(f" ✓ 已删除: {path}")self.report['items_removed'].append(f"用户数据: {path}")self.report['navicat_found'] = Trueexcept Exception as e:self.report['errors'].append(f"无法删除 {path}: {e}")def clean_registry_complete(self):self.logger.log('[4/8] 深度清理注册表...')keys = [(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\PremiumSoft'),(winreg.HKEY_LOCAL_MACHINE, 'SOFTWARE\\WOW6432Node\\PremiumSoft'),(winreg.HKEY_CURRENT_USER, 'SOFTWARE\\PremiumSoft'),(winreg.HKEY_CURRENT_USER, 'SOFTWARE\\Navicat')]for hkey, subkey in keys:try:winreg.DeleteTree(hkey, subkey)self.logger.log(f" ✓ 已删除注册表: {subkey}")self.report['items_removed'].append(f"注册表: {subkey}")self.report['navicat_found'] = Trueexcept:passdef clean_shortcuts(self):self.logger.log('[5/8] 清理快捷方式...')locations = [os.path.expandvars('%USERPROFILE%\\Desktop'),os.path.expandvars('%APPDATA%\\Microsoft\\Windows\\Start Menu\\Programs'),os.path.expandvars('%ProgramData%\\Microsoft\\Windows\\Start Menu\\Programs')]for loc in locations:if not os.path.exists(loc):continuefor root, dirs, files in os.walk(loc):for d in dirs[:]:if 'navicat' in d.lower() or 'premiumsoft' in d.lower():try:shutil.rmtree(os.path.join(root, d))self.logger.log(f" ✓ 删除文件夹: {os.path.join(root, d)}")self.report['items_removed'].append(f"快捷方式文件夹: {os.path.join(root, d)}")dirs.remove(d)self.report['navicat_found'] = Trueexcept:passfor f in files:if not f.lower().endswith('.lnk'):continueif 'navicat' in f.lower() or 'premiumsoft' in f.lower():try:os.remove(os.path.join(root, f))self.logger.log(f" ✓ 删除快捷方式: {os.path.join(root, f)}")self.report['items_removed'].append(f"快捷方式: {os.path.join(root, f)}")self.report['navicat_found'] = Trueexcept:passdef clean_services(self):self.logger.log('[6/8] 清理服务...')service_names = ['Navicat', 'NavicatPremium', 'PremiumSoft', 'NavicatService']for svc in service_names:try:subprocess.run(f"sc stop {svc}", shell=True, capture_output=True)res = subprocess.run(f"sc delete {svc}", shell=True, capture_output=True)if res.returncode == 0:self.logger.log(f" ✓ 已删除服务: {svc}")self.report['items_removed'].append(f"服务: {svc}")self.report['navicat_found'] = Trueexcept:passdef clean_firewall_and_tasks(self):self.logger.log('[7/8] 清理防火墙规则和计划任务...')try:result = subprocess.run('netsh advfirewall firewall show rule name=all | findstr /i navicat', shell=True, capture_output=True, text=True)if result.stdout:subprocess.run('for /f "tokens=2 delims=:" %a in (\'netsh advfirewall firewall show rule name^=all ^| findstr /i "Rule Name:" ^| findstr /i navicat\') do netsh advfirewall firewall delete rule name="%a"', shell=True)self.logger.log(' ✓ 已清理防火墙规则')self.report['items_removed'].append('防火墙规则')self.report['navicat_found'] = Trueexcept:passtry:result = subprocess.run('schtasks /query /fo csv | findstr /i navicat', shell=True, capture_output=True, text=True)if result.stdout:for line in result.stdout.strip().splitlines():task_name = line.split(',')[0].strip('"')subprocess.run(f'schtasks /delete /tn "{task_name}" /f', shell=True)self.logger.log(f" ✓ 删除计划任务: {task_name}")self.report['items_removed'].append(f"计划任务: {task_name}")self.report['navicat_found'] = Trueexcept:passdef deep_scan_and_clean(self):if not self.thorough:returnself.logger.log('[8/8] 执行深度扫描...')keywords = ['navicat', 'premiumsoft', 'patch.exe', 'keygen.exe', 'crack.exe', 'NavicatCrack', 'NavicatKeygen']locations = [os.path.expandvars('%USERPROFILE%'),'C:\\Program Files','C:\\Program Files (x86)','C:\\ProgramData']current_filename = os.path.basename(self.current_exe).lower()current_dir = os.path.dirname(self.current_exe)for loc in locations:if not os.path.exists(loc):continuefor kw in keywords:try:result = subprocess.run(f'where /r "{loc}" *{kw}* 2>nul', shell=True, capture_output=True, text=True, timeout=30)if result.stdout:for fpath in result.stdout.strip().splitlines():fpath_lower = fpath.lower()if os.path.abspath(fpath) == self.current_exe:self.logger.log(f" ⊙ 跳过当前程序: {fpath}")continuebasename = os.path.basename(fpath_lower)if 'cleaner' in basename or 'clean' in basename:self.logger.log(f" ⊙ 跳过清理工具: {fpath}")continueif os.path.dirname(fpath) == current_dir:self.logger.log(f" ⊙ 跳过当前目录文件: {fpath}")continueif self.hostname in basename and ('log' in basename or 'report' in basename):self.logger.log(f" ⊙ 跳过报告文件: {fpath}")continuetry:if os.path.isdir(fpath):shutil.rmtree(fpath, ignore_errors=True)else:os.remove(fpath)self.logger.log(f" ✓ 深度清理: {fpath}")self.report['items_removed'].append(f"深度扫描: {fpath}")self.report['navicat_found'] = Trueexcept Exception as e:self.logger.log(f" ✗ 无法删除: {fpath} - {e}")except Exception as e:self.logger.log(f" ! 扫描出错: {e}")def generate_report(self):self.logger.log('\n生成报告...')json_file = f"{self.hostname}_complete_clean_report.json"txt_file = f"{self.hostname}_complete_clean_report.txt"with open(json_file, 'w', encoding='utf-8') as f:json.dump(self.report, f, ensure_ascii=False, indent=2)with open(txt_file, 'w', encoding='utf-8') as f:f.write('Navicat完整清理报告\n')f.write('==================================================\n')f.write(f"主机名: {self.hostname}\n用户名: {self.username}\n清理时间: {self.report['scan_time']}\n发现Navicat: {'是' if self.report['navicat_found'] else '否'}\n清理项目数: {len(self.report['items_removed'])}\n")if self.report['items_removed']:f.write('\n已清理项目:\n')for item in self.report['items_removed']:f.write(f" - {item}\n")if self.report['errors']:f.write('\n清理失败项目:\n')for err in self.report['errors']:f.write(f" - {err}\n")return json_file, txt_filedef run(self):self.logger.log('==================================================')self.logger.log(' Navicat 完整清理工具 v3.4 (修复版)')self.logger.log('==================================================')self.run_as_admin()self.kill_navicat_processes()self.clean_program_files()self.clean_user_data()self.clean_registry_complete()self.clean_shortcuts()self.clean_services()self.clean_firewall_and_tasks()self.deep_scan_and_clean()json_file, txt_file = self.generate_report()self.logger.log('\n报告已保存:')self.logger.log(f" - {json_file}")self.logger.log(f" - {txt_file}")self.logger.log('\n清理完成!程序运行正常,未自杀 ✓')if not sys.stdout.isatty():import timeself.logger.log('\n非控制台运行,5秒后自动退出...')time.sleep(5)if __name__ == '__main__':thorough = '--thorough' in sys.argv or '-t' in sys.argvcleaner = NavicatCleaner(thorough=thorough)try:cleaner.run()except Exception as e:with open(cleaner.logfile, 'a', encoding='utf-8') as f:f.write(f"运行出错: {e}\n")if sys.stdout.isatty():import tracebacktraceback.print_exc()
可直接执行,不会误删其他的。
