#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
SimpleCard 系统清理工具 - 管理员增强版(智能残留识别+TEMP专项清理)
功能:卡密验证 + 系统深度清理 + 自动自删除 + 清理计时 + 智能TEMP残留识别
优化点:智能判断程序运行残留、多维度识别、并行处理、IO优化
"""
import os
import sys
import time
import shutil
import ctypes
import winreg
import threading
import subprocess
from typing import Optional, Callable, List, Tuple
import tkinter as tk
from tkinter import ttk, messagebox
from datetime import datetime, timedelta
from concurrent.futures import ThreadPoolExecutor, as_completed
import glob
import stat
# 添加当前目录到系统路径
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# ====================== 全局配置与常量 =======================
PROGRESS_CALLBACK: Optional[Callable[[int], None]] = None
TIME_CALLBACK: Optional[Callable[[str], None]] = None
TOTAL_TASKS = 54 # 增加4个任务位(智能残留识别+二次验证+深度扫描)
COMPLETED_TASKS = 0
START_TIME: Optional[datetime] = None
TIMER_THREAD: Optional[threading.Thread] = None
TIMER_RUNNING = False
LOCK = threading.Lock()
# 系统保护目录(禁止删除)
PROTECTED_DIRECTORIES = [
'system volume information', 'recycler', '$recycle.bin',
'windows.old', 'program files', 'programdata',
'system32', 'syswow64'
]
# 基础缓存目录模式(固定匹配)
TEMP_CACHE_PATTERNS = [
'_MEI*', # PyInstaller打包程序临时目录
'jb.station', # 特定程序缓存目录
'pyright-*', # Python相关缓存
'vscode-*', # VSCode临时缓存
'pip-*', # pip缓存目录
'conda-*', # Conda缓存目录
'npm-*', # npm缓存目录
'node_modules-*', # Node.js临时依赖
'chrome-*', # Chrome浏览器临时缓存
'edge-*', # Edge浏览器临时缓存
'firefox-*' # Firefox临时缓存
]
# 智能识别配置
MAX_RESIDUE_DAYS = 7 # 超过7天的临时目录视为残留
MIN_EMPTY_DIR_SIZE = 0 # 空目录直接判定为残留
COMMON_TEMP_FILE_EXT = ['.tmp', '.log', '.cache', '.tmpdir', '.temp'] # 常见临时文件后缀
PYINSTALLER_SIGNATURE_FILES = ['python.exe', 'library.zip', '_MEImanifest'] # PyInstaller临时目录特征文件
# 注册表清理项(保持不变)
REGISTRY_CLEAN_ITEMS: List[Tuple[int, str]] = [
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\OpenSavePidlMRU"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32\LastVisitedPidlMRU"),
(winreg.HKEY_CLASSES_ROOT, r"Local Settings\Software\Microsoft\Windows\Shell\BagMRU"),
(winreg.HKEY_CLASSES_ROOT, r"Local Settings\Software\Microsoft\Windows\Shell\Bags"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist"),
(winreg.HKEY_CLASSES_ROOT, r"Local Settings\Software\Microsoft\Windows\Shell\MuiCache"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU"),
(winreg.HKEY_CURRENT_USER, r"SOFTWARE\WinRAR"),
(winreg.HKEY_CURRENT_USER, r"SOFTWARE\WinRAR SFX"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\RecentDocs")
]
# 回收站相关注册表项(保持不变)
RECYCLE_BIN_REG_ITEMS: List[Tuple[int, str]] = [
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\BitBucket"),
(winreg.HKEY_LOCAL_MACHINE, r"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\BitBucket"),
(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\Shell\Bags\AllFolders\Shell\{645FF040-5081-101B-9F08-00AA002F954E}"),
(winreg.HKEY_CURRENT_USER,
r"Software\Microsoft\Windows\ShellNoRoam\Bags\AllFolders\Shell\{645FF040-5081-101B-9F08-00AA002F954E}"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"),
]
# ====================== 管理员权限相关(保持不变) =======================
def is_admin() -> bool:
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except Exception:
return False
def run_as_admin() -> None:
try:
script_path = os.path.abspath(sys.argv[0])
params = ' '.join(sys.argv[1:])
if ' ' in script_path:
script_path = f'"{script_path}"'
result = ctypes.windll.shell32.ShellExecuteW(
None, "runas", sys.executable, f"{script_path} {params}", None, 1
)
if result <= 32:
raise RuntimeError(f"提权失败,错误码: {result}")
sys.exit(0)
except Exception as e:
messagebox.showerror("提权失败", f"无法获取管理员权限:{str(e)}")
sys.exit(1)
# ====================== 进度与计时更新机制(保持不变) =======================
def update_progress(task_name: str = "") -> None:
global COMPLETED_TASKS
with LOCK:
COMPLETED_TASKS += 1
progress_percent = min(int((COMPLETED_TASKS / TOTAL_TASKS) * 100), 100)
if PROGRESS_CALLBACK and callable(PROGRESS_CALLBACK):
try:
root = tk._get_default_root()
if root:
root.after(0, lambda: PROGRESS_CALLBACK(progress_percent))
else:
PROGRESS_CALLBACK(progress_percent)
except Exception:
PROGRESS_CALLBACK(progress_percent)
if START_TIME:
elapsed_time = datetime.now() - START_TIME
elapsed_str = format_elapsed_time(elapsed_time)
if TIME_CALLBACK and callable(TIME_CALLBACK):
try:
root = tk._get_default_root()
if root:
root.after(0, lambda: TIME_CALLBACK(elapsed_str))
else:
TIME_CALLBACK(elapsed_str)
except Exception:
TIME_CALLBACK(elapsed_str)
print(f"清理进度: {progress_percent}% - 用时: {elapsed_str} - {task_name or '完成一项任务'}")
def reset_progress() -> None:
global COMPLETED_TASKS
with LOCK:
COMPLETED_TASKS = 0
if PROGRESS_CALLBACK and callable(PROGRESS_CALLBACK):
try:
root = tk._get_default_root()
if root:
root.after(0, lambda: PROGRESS_CALLBACK(0))
else:
PROGRESS_CALLBACK(0)
except Exception:
PROGRESS_CALLBACK(0)
global START_TIME
START_TIME = datetime.now()
if TIME_CALLBACK and callable(TIME_CALLBACK):
try:
root = tk._get_default_root()
if root:
root.after(0, lambda: TIME_CALLBACK("00:00:00"))
else:
TIME_CALLBACK("00:00:00")
except Exception:
TIME_CALLBACK("00:00:00")
def format_elapsed_time(elapsed: timedelta) -> str:
total_seconds = int(elapsed.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
seconds = total_seconds % 60
return f"{hours:02d}:{minutes:02d}:{seconds:02d}"
def start_timer() -> None:
global TIMER_RUNNING, TIMER_THREAD
TIMER_RUNNING = True
def timer_worker():
while TIMER_RUNNING:
if START_TIME:
elapsed_time = datetime.now() - START_TIME
elapsed_str = format_elapsed_time(elapsed_time)
if TIME_CALLBACK and callable(TIME_CALLBACK):
try:
root = tk._get_default_root()
if root and TIMER_RUNNING:
root.after(0, lambda: TIME_CALLBACK(elapsed_str))
except Exception:
pass
time.sleep(1)
TIMER_THREAD = threading.Thread(target=timer_worker, daemon=True)
TIMER_THREAD.start()
def stop_timer() -> None:
global TIMER_RUNNING
TIMER_RUNNING = False
if TIMER_THREAD:
TIMER_THREAD.join(timeout=2)
# ====================== 核心文件操作工具(增强智能识别) =======================
def remove_file_attributes_batch(file_paths: List[str]) -> None:
if not file_paths:
return
paths_str = ' '.join([f'"{path}"' for path in file_paths if os.path.exists(path)])
if not paths_str:
return
try:
subprocess.run(
['cmd.exe', '/C', f'attrib -r -s -h /s /d {paths_str}'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True,
timeout=10
)
except Exception:
pass
def delete_with_retry(file_path: str, max_retries: int = 3) -> bool:
"""增强删除重试逻辑,支持强制删除"""
if not os.path.exists(file_path):
return True
if is_protected_path(file_path):
return False
# 先尝试正常删除
for retry in range(max_retries):
try:
if os.path.isfile(file_path) or os.path.islink(file_path):
os.chmod(file_path, stat.S_IWRITE) # 解除只读
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path, ignore_errors=True)
if not os.path.exists(file_path):
return True
except Exception:
time.sleep(0.5)
# 强制删除(针对顽固文件)
try:
if os.path.isfile(file_path):
subprocess.run(
['cmd.exe', '/C', 'del /f /q /a:rhs ' + file_path],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True,
timeout=8
)
else:
subprocess.run(
['cmd.exe', '/C', 'rmdir /s /q ' + file_path],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True,
timeout=8
)
return not os.path.exists(file_path)
except Exception:
print(f"警告:无法删除 {file_path}(可能被核心进程占用)")
return False
def is_protected_path(path: str) -> bool:
path_lower = path.lower()
return any(protected in path_lower for protected in PROTECTED_DIRECTORIES)
def batch_delete_files_parallel(file_paths: List[str]) -> None:
if not file_paths:
return
remove_file_attributes_batch(file_paths)
with ThreadPoolExecutor(max_workers=10) as executor: # 增加线程数提升删除速度
executor.map(delete_with_retry, file_paths)
def find_files_by_pattern(directory: str, patterns: List[str]) -> List[str]:
if not os.path.exists(directory) or is_protected_path(directory):
return []
matched_files = []
try:
for pattern in patterns:
search_pattern = os.path.join(directory, pattern)
matched_files.extend(glob.glob(search_pattern))
matched_files = list(set([
f for f in matched_files
if not is_protected_path(f) and os.path.exists(f)
]))
except Exception:
pass
return matched_files
# ====================== 智能残留识别核心函数(新增) =======================
def get_file_creation_time(file_path: str) -> Optional[datetime]:
"""获取文件/目录的创建时间"""
try:
stat_info = os.stat(file_path)
# Windows系统使用st_ctime作为创建时间
creation_time = datetime.fromtimestamp(stat_info.st_ctime)
return creation_time
except Exception:
return None
def is_pyinstaller_temp_dir(dir_path: str) -> bool:
"""判断是否为PyInstaller生成的临时目录(智能识别)"""
if not os.path.isdir(dir_path) or is_protected_path(dir_path):
return False
# 检查目录名是否以_MEI开头(基础判断)
dir_name = os.path.basename(dir_path)
if dir_name.startswith('_MEI') and len(dir_name) >= 6: # _MEI + 至少3位数字
# 检查目录内是否有PyInstaller特征文件
for sig_file in PYINSTALLER_SIGNATURE_FILES:
if os.path.exists(os.path.join(dir_path, sig_file)):
return True
# 即使没有特征文件,长时间未修改的_MEI目录也视为残留
create_time = get_file_creation_time(dir_path)
if create_time and (datetime.now() - create_time).days >= 1:
return True
return False
def is_program_residue_dir(dir_path: str) -> bool:
"""智能判断是否为程序运行残留目录(多维度识别)"""
if not os.path.isdir(dir_path) or is_protected_path(dir_path):
return False
dir_name = os.path.basename(dir_path).lower()
create_time = get_file_creation_time(dir_path)
# 维度1:目录名包含临时特征关键词
temp_keywords = ['temp', 'tmp', 'cache', 'cache-', 'runtime', 'run-', 'session', 'session-']
if any(keyword in dir_name for keyword in temp_keywords):
return True
# 维度2:创建时间超过指定天数
if create_time and (datetime.now() - create_time).days >= MAX_RESIDUE_DAYS:
return True
# 维度3:空目录(无任何文件)
try:
if not os.listdir(dir_path):
return True
except Exception:
pass
# 维度4:目录内全是临时文件(后缀匹配)
try:
all_temp = True
for root, _, files in os.walk(dir_path):
for file in files:
file_ext = os.path.splitext(file)[1].lower()
if file_ext not in COMMON_TEMP_FILE_EXT and not file.lower().startswith('temp'):
all_temp = False
break
if not all_temp:
break
if all_temp:
return True
except Exception:
pass
# 维度5:目录大小过小(疑似临时缓存)
try:
total_size = 0
for root, _, files in os.walk(dir_path):
for file in files:
file_path = os.path.join(root, file)
total_size += os.path.getsize(file_path)
if total_size > 1024 * 1024: # 超过1MB则不视为临时残留
return False
return True
except Exception:
pass
return False
def scan_temp_residues_smartly(temp_dirs: List[str]) -> List[str]:
"""智能扫描所有TEMP目录中的程序残留(固定模式+智能识别)"""
print("\n开始智能扫描程序运行残留...")
all_residues = []
with ThreadPoolExecutor(max_workers=6) as executor:
future_to_dir = {}
def scan_single_dir(temp_dir):
"""扫描单个TEMP目录的残留"""
residues = []
if not os.path.exists(temp_dir) or is_protected_path(temp_dir):
return residues
print(f"智能扫描: {temp_dir}")
# 步骤1:固定模式匹配(快速清理已知残留)
fixed_pattern_residues = find_files_by_pattern(temp_dir, TEMP_CACHE_PATTERNS)
residues.extend(fixed_pattern_residues)
# 步骤2:智能识别未知残留(遍历所有子目录)
try:
for item in os.listdir(temp_dir):
item_path = os.path.join(temp_dir, item)
if os.path.isdir(item_path) and item_path not in residues:
# 识别PyInstaller临时目录
if is_pyinstaller_temp_dir(item_path):
residues.append(item_path)
# 识别通用程序残留目录
elif is_program_residue_dir(item_path):
residues.append(item_path)
except Exception as e:
print(f"扫描目录 {temp_dir} 时出错: {str(e)}")
return residues
# 提交所有目录扫描任务
for temp_dir in temp_dirs:
future = executor.submit(scan_single_dir, temp_dir)
future_to_dir[future] = temp_dir
# 收集扫描结果
for future in as_completed(future_to_dir):
residues = future.result()
all_residues.extend(residues)
# 去重并过滤不存在的路径
all_residues = list(set([
res for res in all_residues
if os.path.exists(res) and not is_protected_path(res)
]))
print(f"智能扫描完成:发现 {len(all_residues)} 个程序运行残留项")
if all_residues:
print("发现的残留项:")
for res in all_residues[:10]: # 只打印前10个
print(f" - {res}")
if len(all_residues) > 10:
print(f" ... 还有 {len(all_residues) - 10} 个残留项")
return all_residues
# ====================== TEMP专项清理(增强智能识别) =======================
def clean_temp_cache_directories() -> None:
"""增强版:固定模式+智能识别 清理TEMP目录程序残留"""
try:
print("\n开始TEMP目录专项清理(固定模式+智能识别)...")
# 收集所有系统TEMP目录(覆盖用户级+系统级)
temp_directories = list(set([
f for f in [
os.environ.get('TEMP', ''),
os.environ.get('TMP', ''),
os.path.join(os.environ.get('WINDIR', ''), 'Temp'),
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp'),
os.path.join(os.environ.get('USERPROFILE', ''), 'AppData', 'Local', 'Temp'),
os.path.join(os.environ.get('ALLUSERSPROFILE', ''), 'Temp'),
os.path.join(os.environ.get('PUBLIC', ''), 'Temp'),
os.path.join(os.environ.get('APPDATA', ''), 'Temp'),
os.path.join(os.environ.get('PROGRAMDATA', ''), 'Temp'),
]
if f and os.path.exists(f) and not is_protected_path(f)
]))
if not temp_directories:
print("未找到可用的TEMP目录")
update_progress("TEMP专项清理:无可用目录")
return
# 智能扫描所有残留
all_residues = scan_temp_residues_smartly(temp_directories)
if all_residues:
# 并行删除残留项(高效清理)
batch_delete_files_parallel(all_residues)
# 第一次验证清理结果
remaining_residues = []
for residue in all_residues:
if os.path.exists(residue):
remaining_residues.append(residue)
# 对未清理成功的残留进行二次强制清理
if remaining_residues:
print(f"第一次清理后剩余 {len(remaining_residues)} 个残留项,尝试二次强制清理...")
batch_delete_files_parallel(remaining_residues)
# 第二次验证
final_remaining = [res for res in remaining_residues if os.path.exists(res)]
if final_remaining:
print(f"警告:以下残留项仍未清理成功(可能被占用):")
for res in final_remaining[:5]:
print(f" - {res}")
update_progress(
f"TEMP专项清理完成(已清理 {len(all_residues) - len(final_remaining)} 个,剩余 {len(final_remaining)} 个)")
else:
update_progress(f"TEMP专项清理完成(已清理全部 {len(all_residues)} 个残留项)")
else:
update_progress(f"TEMP专项清理完成(已清理全部 {len(all_residues)} 个残留项)")
except Exception as e:
print(f"清理TEMP专项缓存时出错: {str(e)}")
update_progress("TEMP专项缓存清理失败")
def deep_verify_temp_cleanup() -> None:
"""深度验证TEMP清理结果,确保无遗漏"""
try:
print("\n深度验证TEMP目录清理结果...")
temp_directories = list(set([
os.environ.get('TEMP', ''),
os.environ.get('TMP', ''),
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp'),
]))
# 再次智能扫描,确认是否有遗漏
remaining_residues = scan_temp_residues_smartly(temp_directories)
if remaining_residues:
print(f"深度验证发现 {len(remaining_residues)} 个遗漏残留项,进行补充清理...")
batch_delete_files_parallel(remaining_residues)
final_remaining = [res for res in remaining_residues if os.path.exists(res)]
if final_remaining:
update_progress(
f"TEMP深度验证:补充清理 {len(remaining_residues) - len(final_remaining)} 个,残留 {len(final_remaining)} 个")
else:
update_progress("TEMP深度验证:补充清理完成,无残留")
else:
print("TEMP目录无残留缓存项,清理彻底")
update_progress("TEMP深度验证:无残留,清理彻底")
except Exception as e:
print(f"深度验证TEMP清理结果时出错: {str(e)}")
update_progress("TEMP深度验证失败")
# ====================== SimpleCard 模块导入(保持不变) =======================
try:
from simple_card_validator import CardValidator
from simple_card_config import ConfigManager
except ImportError as e:
if is_admin():
messagebox.showerror("导入错误",
f"无法导入 SimpleCard 模块:{str(e)}\n请确保所有 simple_card_* 文件已正确放置在同一目录")
sys.exit(1)
# ====================== 系统清理核心功能(保持不变) =======================
def delete_files_by_pattern_optimized(directory: str, patterns: List[str]) -> None:
try:
if not os.path.exists(directory) or is_protected_path(directory):
update_progress(f"跳过受保护目录: {directory}")
return
matched_files = find_files_by_pattern(directory, patterns)
if matched_files:
batch_delete_files_parallel(matched_files)
update_progress(f"清理模式 {patterns} 完成(共处理 {len(matched_files)} 个文件)")
except Exception as e:
print(f"清理目录 {directory} 时出错: {str(e)}")
update_progress(f"目录 {directory} 清理失败")
def delete_folder_contents_optimized(folder: str) -> None:
try:
if not os.path.exists(folder) or is_protected_path(folder):
update_progress(f"跳过受保护目录: {folder}")
return
all_items = []
for root, dirs, files in os.walk(folder, topdown=False):
if is_protected_path(root):
continue
for file in files:
all_items.append(os.path.join(root, file))
for dir_name in dirs:
dir_path = os.path.join(root, dir_name)
if not is_protected_path(dir_path):
all_items.append(dir_path)
batch_delete_files_parallel(all_items)
update_progress(f"清理目录 {os.path.basename(folder)} 完成(共处理 {len(all_items)} 个项)")
except Exception as e:
print(f"清理目录 {folder} 时出错: {str(e)}")
update_progress(f"目录 {folder} 清理失败")
def recreate_temp_folder_optimized(folder: str) -> None:
try:
if is_protected_path(folder):
update_progress(f"跳过系统目录: {folder}")
return
if os.path.exists(folder):
delete_with_retry(folder, max_retries=2)
if not os.path.exists(folder):
os.makedirs(folder, exist_ok=True)
os.chmod(folder, 0o777)
update_progress(f"重建目录 {os.path.basename(folder)} 完成")
except Exception as e:
print(f"重建目录 {folder} 时出错: {str(e)}")
update_progress(f"目录 {folder} 重建失败")
def delete_registry_key_optimized(root: int, subkey: str) -> None:
try:
access = winreg.KEY_ALL_ACCESS | winreg.KEY_WOW64_64KEY
try:
with winreg.OpenKey(root, "", 0, access) as parent_key:
winreg.DeleteKeyEx(parent_key, subkey)
update_progress(f"删除注册表项 {subkey}")
except WindowsError as e:
if e.winerror == 2:
update_progress(f"注册表项 {subkey} 不存在")
else:
raise
except Exception as e:
print(f"删除注册表项 {subkey} 时出错: {str(e)}")
update_progress(f"注册表项 {subkey} 删除失败")
def clear_ie_history_optimized() -> None:
try:
ie_cmd = (
"RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 1 && "
"RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 2 && "
"RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8 && "
"RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 16 && "
"RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 32 && "
"RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 255"
)
subprocess.run(
ie_cmd,
shell=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
timeout=15
)
update_progress("IE浏览器历史清理完成")
except Exception as e:
print(f"清理IE历史时出错: {str(e)}")
update_progress("IE浏览器历史清理失败")
def clear_temp_files_optimized() -> None:
try:
temp_folders = list(set([
f for f in [
os.environ.get('TEMP', ''),
os.environ.get('TMP', ''),
os.path.join(os.environ.get('WINDIR', ''), 'Temp'),
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp'),
os.path.join(os.environ.get('USERPROFILE', ''), 'AppData', 'Local', 'Temp'),
os.path.join(os.environ.get('USERPROFILE', ''), 'Local Settings', 'Temp'),
os.path.join(os.environ.get('ALLUSERSPROFILE', ''), 'Temp'),
os.path.join(os.environ.get('PUBLIC', ''), 'Temp'),
os.path.join(os.environ.get('APPDATA', ''), 'Temp'),
]
if f and os.path.exists(f) and not is_protected_path(f)
]))
print(f"发现 {len(temp_folders)} 个临时目录待清理(并行处理)")
with ThreadPoolExecutor(max_workers=4) as executor:
executor.map(delete_folder_contents_optimized, temp_folders)
update_progress("所有临时文件清理完成")
except Exception as e:
print(f"清理临时文件时出错: {str(e)}")
update_progress("临时文件清理失败")
def clear_recycle_bin_optimized() -> None:
try:
print("开始清理回收站...")
subprocess.run(
['powershell.exe', '-Command', 'Clear-RecycleBin -Force -ErrorAction SilentlyContinue'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True,
timeout=30
)
subprocess.run(
['cmd.exe', '/C', 'for /d %d in (*:) do @if exist "%d\\$Recycle.Bin" rd /s /q "%d\\$Recycle.Bin"'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
shell=True,
timeout=30
)
update_progress("回收站清理完成")
except Exception as e:
print(f"清理回收站时出错: {str(e)}")
update_progress("回收站清理失败")
def full_registry_cleanup_optimized() -> None:
try:
print("开始执行注册表清理...")
with ThreadPoolExecutor(max_workers=5) as executor:
def registry_worker(root_key, subkey):
delete_registry_key_optimized(root_key, subkey)
executor.map(lambda x: registry_worker(x[0], x[1]), REGISTRY_CLEAN_ITEMS)
update_progress("完整注册表清理完成")
except Exception as e:
print(f"注册表清理时出错: {str(e)}")
remaining = 10 - (COMPLETED_TASKS % 10)
for _ in range(remaining):
update_progress("注册表清理跳过任务")
def batch_delete_files_optimized(system_drive: str, windir: str, userprofile: str, appdata: str) -> None:
try:
pattern_mapping = [
(system_drive, ['*._mp', '*.log', '*.gid', '*.chk', '*.old', '*.tmp']),
(windir, ['*.bak']),
]
all_files = []
for dir_path, patterns in pattern_mapping:
all_files.extend(find_files_by_pattern(dir_path, patterns))
batch_delete_files_parallel(all_files)
special_folders = [
os.path.join(system_drive, 'recycled'),
os.path.join(windir, 'prefetch'),
os.path.join(userprofile, 'cookies'),
os.path.join(userprofile, 'recent'),
os.path.join(appdata, 'Microsoft', 'Windows', 'Recent'),
os.path.join(userprofile, 'Local Settings', 'Temporary Internet Files'),
os.path.join(userprofile, 'Local Settings', 'Temp'),
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Microsoft', 'Windows', 'Temporary Internet Files'),
os.path.join(os.environ.get('LOCALAPPDATA', ''), 'Temp'),
]
valid_folders = [f for f in special_folders if os.path.exists(f) and not is_protected_path(f)]
with ThreadPoolExecutor(max_workers=4) as executor:
executor.map(delete_folder_contents_optimized, valid_folders)
explorer_folder = os.path.join(appdata, 'Microsoft', 'Windows', 'Explorer')
if os.path.exists(explorer_folder):
search_files = find_files_by_pattern(explorer_folder, ['search*.search-ms'])
batch_delete_files_parallel(search_files)
update_progress("Explorer搜索历史清理完成")
typedpaths_file = os.path.join(explorer_folder, 'TypedPaths')
if os.path.exists(typedpaths_file):
delete_with_retry(typedpaths_file)
update_progress("TypedPaths清理完成")
except Exception as e:
print(f"批量文件删除时出错: {str(e)}")
remaining = 16 - (COMPLETED_TASKS % 16)
for _ in range(remaining):
update_progress("批量删除跳过任务")
# ====================== 主清理流程(增强智能残留清理) =======================
def main_clean(progress_callback: Callable[[int], None] = None, time_callback: Callable[[str], None] = None) -> bool:
global PROGRESS_CALLBACK, TIME_CALLBACK
PROGRESS_CALLBACK = progress_callback
TIME_CALLBACK = time_callback
print("=" * 60)
print(
f"开始执行系统深度清理(智能残留识别+TEMP专项清理)... 启动时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
print("=" * 60)
reset_progress()
start_timer()
try:
system_drive = os.environ.get('SYSTEMDRIVE', 'C:')
windir = os.environ.get('WINDIR', 'C:\\Windows')
user_profile = os.environ.get('USERPROFILE', os.path.expanduser('~'))
appdata = os.environ.get('APPDATA', os.path.join(user_profile, 'AppData', 'Roaming'))
# 并行任务(保持不变)
parallel_tasks = [
("批量文件删除", lambda: batch_delete_files_optimized(system_drive, windir, user_profile, appdata)),
("Shell目录清理", clear_local_settings_shell),
("注册表清理", full_registry_cleanup_optimized),
("IE历史清理", clear_ie_history_optimized),
("临时文件清理", clear_temp_files_optimized),
]
# 串行任务(增强:智能残留清理+深度验证)
serial_tasks = [
("运行记录清理", clear_run_history),
("系统目录重建", lambda: [
recreate_temp_folder_optimized(os.path.join(windir, 'temp')),
recreate_temp_folder_optimized(os.environ.get('TEMP', '')),
recreate_temp_folder_optimized(os.environ.get('TMP', ''))
]),
("事件日志清理", clear_event_logs),
("配置文件删除", delete_config_files),
("回收站清理", clear_recycle_bin_optimized),
("回收站注册表清理", clear_recycle_bin_registry),
("TEMP智能残留清理", clean_temp_cache_directories), # 增强版:固定模式+智能识别
("TEMP深度验证清理", deep_verify_temp_cleanup) # 新增:深度验证无遗漏
]
# 并行执行独立任务
print("\n开始并行执行清理任务...")
with ThreadPoolExecutor(max_workers=3) as executor:
def task_worker(step_name, step_func):
print(f"执行: {step_name} - 当前时间: {datetime.now().strftime('%H:%M:%S')}")
try:
step_func()
except Exception as e:
print(f"步骤 {step_name} 执行失败: {str(e)}")
futures = [executor.submit(task_worker, name, func) for name, func in parallel_tasks]
for future in as_completed(futures):
future.result()
# 串行执行剩余任务(包含智能残留清理)
print("\n开始串行执行剩余任务(含智能残留清理)...")
for step_name, step_func in serial_tasks:
print(f"执行: {step_name} - 当前时间: {datetime.now().strftime('%H:%M:%S')}")
try:
step_func()
except Exception as e:
print(f"步骤 {step_name} 执行失败: {str(e)}")
# 确保进度达到100%
if PROGRESS_CALLBACK and callable(PROGRESS_CALLBACK):
root = tk._get_default_root()
if root:
root.after(0, lambda: PROGRESS_CALLBACK(100))
else:
PROGRESS_CALLBACK(100)
# 停止计时并计算总用时
stop_timer()
total_time = datetime.now() - START_TIME
total_time_str = format_elapsed_time(total_time)
print("\n" + "=" * 60)
print(f"清理流程完成!总用时: {total_time_str}(智能残留识别+TEMP专项清理)")
print("=" * 60)
# 显示完成信息(更新智能清理描述)
time.sleep(1)
messagebox.showinfo(
"清理完成",
f"✅ 系统深度清理已完成!\n\n总用时:{total_time_str}(智能残留识别+TEMP专项清理)\n\n已清理内容:\n"
"1. 所有临时文件和缓存(TEMP目录彻底清理)\n"
"2. 程序运行残留(智能识别+固定模式,含_MEIxxx、jb.station等)\n"
"3. 注册表垃圾项和历史记录\n"
"4. IE浏览器历史、Cookie和表单数据\n"
"5. 回收站所有文件\n"
"6. 最近访问记录和运行历史\n"
"7. 系统事件日志\n\n"
"智能识别能力:\n"
"- 自动判断PyInstaller临时目录(_MEIxxx)\n"
"- 识别空目录、过期目录(超过7天)\n"
"- 识别全临时文件目录、小体积缓存目录\n"
"- 二次强制清理+深度验证,确保无残留\n\n"
"程序将在5秒后自动删除,不留痕迹。"
)
# 延迟后自删除
time.sleep(5)
self_delete()
return True
except Exception as e:
stop_timer()
if START_TIME:
total_time = datetime.now() - START_TIME
total_time_str = format_elapsed_time(total_time)
else:
total_time_str = "未知"
error_msg = f"清理过程中发生错误: {str(e)}"
print(f"\n{error_msg}")
print(f"已用时: {total_time_str}")
if PROGRESS_CALLBACK and callable(PROGRESS_CALLBACK):
root = tk._get_default_root()
if root:
root.after(0, lambda: PROGRESS_CALLBACK(100))
else:
PROGRESS_CALLBACK(100)
messagebox.showerror(
"清理错误",
f"⚠️ 系统清理过程中发生错误:\n{str(e)}\n\n"
f"已运行时间:{total_time_str}\n\n"
"已尽力完成部分清理工作,主要包括:\n"
"- 临时文件清理\n"
"- 程序运行残留(智能识别+固定模式)\n"
"- 缓存文件清理\n"
"- 部分注册表清理\n\n"
"程序将在5秒后自动删除。"
)
time.sleep(5)
self_delete()
return False
# ====================== 保留原有未优化但必要的函数(保持不变) =======================
def delete_config_files() -> None:
try:
config_paths = [
"config.ini",
os.path.join(os.path.dirname(__file__), "config.ini"),
os.path.join(os.environ.get('APPDATA', ''), "SimpleCard", "config.ini"),
os.path.join(os.environ.get('LOCALAPPDATA', ''), "SimpleCard", "config.ini"),
]
deleted_count = 0
for config_path in config_paths:
if os.path.exists(config_path):
if delete_with_retry(config_path):
deleted_count += 1
print(f"已删除配置文件: {config_path}")
update_progress(f"删除配置文件 {deleted_count} 个")
except Exception as e:
print(f"删除配置文件时出错: {str(e)}")
update_progress("配置文件删除失败")
def clear_run_history() -> None:
try:
reg_keys = [
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU"),
(winreg.HKEY_CURRENT_USER, r"Software\Microsoft\Windows\CurrentVersion\Explorer\TypedPaths"),
]
for root_key, subkey in reg_keys:
delete_registry_key_optimized(root_key, subkey)
recent_folder = os.path.join(os.environ.get('USERPROFILE', ''), 'Recent')
if os.path.exists(recent_folder):
delete_folder_contents_optimized(recent_folder)
update_progress("运行记录清理完成")
except Exception as e:
print(f"清理运行记录时出错: {str(e)}")
update_progress("运行记录清理失败")
def clear_event_logs() -> None:
try:
event_logs = ["Application", "System", "Security", "Setup"]
for log_name in event_logs:
try:
subprocess.run(
['wevtutil', 'cl', log_name],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
timeout=8
)
except Exception:
continue
update_progress("系统事件日志清理完成")
except Exception as e:
print(f"清理事件日志时出错: {str(e)}")
update_progress("事件日志清理失败")
def self_delete() -> None:
try:
script_path = os.path.abspath(sys.argv[0])
if not os.path.exists(script_path):
update_progress("自删除:程序文件不存在")
return
is_exe = script_path.lower().endswith(('.exe', '.com', '.bat', '.cmd'))
bat_path = os.path.join(os.getenv('TEMP', ''), 'admin_self_delete.bat')
with open(bat_path, 'w', encoding='utf-8') as bat_file:
bat_content = f"""@echo off
chcp 65001 > nul
ping 127.0.0.1 -n 8 > nul
"""
if is_exe:
exe_name = os.path.basename(script_path)
bat_content += f"""taskkill /f /im "{exe_name}" 2>nul
ping 127.0.0.1 -n 2 > nul
"""
bat_content += f"""del /f /q /a "{script_path}"
del /f /q /a "{script_path}.log" 2>nul
del /f /q /a "{os.path.splitext(script_path)[0]}.log" 2>nul
del /f /q /a "{os.path.splitext(script_path)[0]}.pdb" 2>nul
del /f /q "%TEMP%\\*.*" /s /q 2>nul
rmdir /s /q "%TEMP%\\SimpleCard" 2>nul
rmdir /s /q "%LOCALAPPDATA%\\Temp\\SimpleCard" 2>nul
del /f /q "{bat_path}"
"""
bat_file.write(bat_content)
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.Popen(
['cmd.exe', '/C', bat_path],
shell=True,
stdin=None,
stdout=None,
stderr=None,
close_fds=True,
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP,
startupinfo=startupinfo
)
update_progress("自删除脚本已启动")
except Exception as e:
print(f"创建自删除脚本时出错: {str(e)}")
update_progress("自删除脚本创建失败")
def clear_recycle_bin_registry() -> None:
try:
print("开始清理回收站注册表...")
for root_key, subkey in RECYCLE_BIN_REG_ITEMS:
try:
if "Shell Folders" in subkey or "User Shell Folders" in subkey:
try:
access = winreg.KEY_ALL_ACCESS | winreg.KEY_WOW64_64KEY
with winreg.OpenKey(root_key, subkey, 0, access) as key:
for value_name in ['Recycle Bin', 'Recycled', '{645FF040-5081-101B-9F08-00AA002F954E}']:
try:
winreg.DeleteValue(key, value_name)
except Exception:
continue
except Exception:
continue
else:
delete_registry_key_optimized(root_key, subkey)
except Exception:
continue
update_progress("回收站注册表清理完成")
except Exception as e:
print(f"清理回收站注册表时出错: {str(e)}")
update_progress("回收站注册表清理失败")
def clear_local_settings_shell() -> None:
try:
print("开始清理Shell缓存目录...")
user_profile = os.environ.get('USERPROFILE', os.path.expanduser('~'))
old_shell_path = os.path.join(user_profile, 'Local Settings', 'Shell')
if os.path.exists(old_shell_path):
delete_folder_contents_optimized(old_shell_path)
new_shell_path = os.path.join(
os.environ.get('LOCALAPPDATA', os.path.join(user_profile, 'AppData', 'Local')),
'Microsoft', 'Windows', 'Shell'
)
if os.path.exists(new_shell_path):
delete_dirs = []
for item in os.listdir(new_shell_path):
item_path = os.path.join(new_shell_path, item)
if os.path.isdir(item_path) and any(
name in item.lower() for name in ['cache', 'history', 'recent']
):
delete_dirs.append(item_path)
batch_delete_files_parallel(delete_dirs)
update_progress("Shell缓存目录清理完成")
except Exception as e:
print(f"清理Shell目录时出错: {str(e)}")
update_progress("Shell目录清理失败")
# ====================== 进度窗口(更新智能清理描述) =======================
class CleanProgressWindow:
def __init__(self, parent=None):
self.root = tk.Toplevel(parent)
self.root.title("系统清理进度 - 计时中(智能残留识别+TEMP专项清理)") # 更新标题
self.root.geometry("450x180")
self.root.resizable(False, False)
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
if parent:
self.root.grab_set()
self.root.attributes('-topmost', True)
self.is_cleaning = True
self.create_widgets()
self.root.lift()
def create_widgets(self):
main_frame = ttk.Frame(self.root, padding="30")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
title_label = ttk.Label(
main_frame,
text="正在执行系统深度清理(智能残留识别+TEMP专项清理)", # 更新标题
font=("Arial", 14, "bold")
)
title_label.grid(row=0, column=0, columnspan=2, pady=(0, 15))
time_frame = ttk.Frame(main_frame)
time_frame.grid(row=1, column=0, columnspan=2, pady=(0, 10))
ttk.Label(
time_frame,
text="已用时:",
font=("Arial", 11)
).pack(side=tk.LEFT, padx=(0, 10))
self.time_label = ttk.Label(
time_frame,
text="00:00:00",
font=("Arial", 12, "bold"),
foreground="#2E86AB"
)
self.time_label.pack(side=tk.LEFT)
self.progress_var = tk.DoubleVar(value=0)
self.progress_bar = ttk.Progressbar(
main_frame,
variable=self.progress_var,
maximum=100,
mode="determinate",
length=380
)
self.progress_bar.grid(row=2, column=0, columnspan=2, pady=(0, 15))
self.progress_label = ttk.Label(
main_frame,
text="进度: 0%",
font=("Arial", 12, "bold")
)
self.progress_label.grid(row=3, column=0, columnspan=2)
main_frame.columnconfigure(0, weight=1)
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
def update_progress(self, percent: int):
self.progress_var.set(percent)
self.progress_label.config(text=f"进度: {percent}%")
self.root.update_idletasks()
self.root.lift()
def update_time(self, time_str: str):
self.time_label.config(text=time_str)
self.root.update_idletasks()
def on_closing(self):
messagebox.showwarning("警告", "清理过程中不能关闭窗口!\n请等待清理完成后程序会自动退出。")
def destroy(self):
self.is_cleaning = False
try:
self.root.grab_release()
except Exception:
pass
self.root.destroy()
# ====================== 主GUI界面(更新智能清理描述) =======================
class SimpleCardCleanGUI:
def __init__(self):
print("=== 启动 SimpleCard 系统清理工具(智能残留识别+计时+速度优化)===") # 更新描述
self.root = tk.Tk()
self.root.title("SimpleCard 验证系统 - 管理员模式(智能残留识别+TEMP专项清理)") # 更新标题
self.root.geometry("450x480") # 增加高度显示更多信息
self.root.resizable(False, False)
self.validator = CardValidator()
self.progress_window: Optional[CleanProgressWindow] = None
self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
self.card_no_var = tk.StringVar()
self.save_pwd_var = tk.BooleanVar(value=False)
self.auto_login_var = tk.BooleanVar(value=False)
self.create_widgets()
self.initialize()
def create_widgets(self):
main_frame = ttk.Frame(self.root, padding="15")
main_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
title_label = ttk.Label(
main_frame,
text="蜡笔小新团队",
font=("Arial", 18, "bold")
)
title_label.grid(row=0, column=0, pady=(0, 15))
admin_label = ttk.Label(
main_frame,
text="✅ 已获取管理员权限",
font=("Arial", 10, "bold"),
foreground="green"
)
admin_label.grid(row=0, column=0, pady=(40, 0))
notice_frame = ttk.LabelFrame(main_frame, text="系统通知(智能残留识别+TEMP专项清理)", padding="10") # 更新标题
notice_frame.grid(row=1, column=0, sticky=(tk.W, tk.E), pady=(0, 15))
self.notice_text = tk.Text(
notice_frame,
height=5, # 增加行数
width=45,
wrap=tk.WORD,
font=("Arial", 9)
)
self.notice_text.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
notice_scrollbar = ttk.Scrollbar(
notice_frame,
orient="vertical",
command=self.notice_text.yview
)
notice_scrollbar.grid(row=0, column=1, sticky=(tk.N, tk.S))
self.notice_text.configure(yscrollcommand=notice_scrollbar.set)
login_frame = ttk.LabelFrame(main_frame, text="登录验证", padding="15")
login_frame.grid(row=2, column=0, sticky=(tk.W, tk.E), pady=(0, 15))
ttk.Label(login_frame, text="卡号:", font=("Arial", 10)).grid(
row=0, column=0, sticky=tk.W, pady=8
)
self.card_entry = ttk.Entry(
login_frame,
textvariable=self.card_no_var,
width=30,
font=("Arial", 10),
show="*"
)
self.card_entry.grid(row=0, column=1, pady=8, sticky=(tk.W, tk.E))
checkbox_frame = ttk.Frame(login_frame)
checkbox_frame.grid(row=1, column=0, columnspan=2, pady=12)
self.save_pwd_check = ttk.Checkbutton(
checkbox_frame,
text="记住卡号",
variable=self.save_pwd_var
)
self.save_pwd_check.pack(side=tk.LEFT, padx=(0, 25))
self.auto_login_check = ttk.Checkbutton(
checkbox_frame,
text="自动登录",
variable=self.auto_login_var
)
self.auto_login_check.pack(side=tk.LEFT)
button_frame = ttk.Frame(main_frame)
button_frame.grid(row=3, column=0, pady=(10, 15))
self.login_button = ttk.Button(
button_frame,
text="登 录",
width=12,
command=self.on_login_click
)
self.login_button.pack(side=tk.LEFT, padx=(0, 15))
self.unbind_button = ttk.Button(
button_frame,
text="解 绑",
width=12,
command=self.on_unbind_click
)
self.unbind_button.pack(side=tk.LEFT)
self.status_var = tk.StringVar(value="界面就绪 - 智能识别程序残留,清理更彻底(不影响系统稳定)") # 更新描述
status_bar = ttk.Label(
self.root,
textvariable=self.status_var,
relief=tk.SUNKEN,
anchor=tk.W,
font=("Arial", 9)
)
status_bar.grid(row=1, column=0, sticky=(tk.W, tk.E))
self.root.columnconfigure(0, weight=1)
self.root.rowconfigure(0, weight=1)
main_frame.columnconfigure(1, weight=1)
login_frame.columnconfigure(1, weight=1)
def initialize(self):
try:
self.update_status("正在初始化验证系统(智能残留识别+TEMP专项清理)...") # 更新描述
self.update_notice(
"欢迎使用系统清理工具(智能残留识别+计时+速度优化)!\n" # 更新描述
"核心亮点:\n"
"1. 智能识别程序运行残留(无需手动添加模式)\n"
"2. 自动判断_MEIxxx、jb.station等已知残留\n"
"3. 识别空目录、过期目录、临时文件目录\n"
"4. 二次强制清理+深度验证,无遗漏\n"
"5. 并行处理,速度提升50%+,不影响系统稳定\n"
"提示:验证成功后自动运行深度清理,实时显示用时。"
)
threading.Thread(target=self.init_worker, daemon=True).start()
except Exception as e:
self.show_error(f"初始化失败:{str(e)}")
def init_worker(self):
try:
if not self.validator.get_encrypt_key():
self.root.after(0, lambda: self.show_error("获取加密密钥失败"))
return
token_result = self.validator.get_token()
if not token_result:
if hasattr(self.validator, 'version_update_needed') and self.validator.version_update_needed:
self.root.after(0, self.show_version_update)
return
card_no, save_pwd, auto_login = self.validator.config.load_config()
self.root.after(0, lambda: self.on_init_complete(card_no, save_pwd, auto_login))
except Exception as e:
self.root.after(0, lambda: self.show_error(f"初始化异常:{str(e)}"))
def on_init_complete(self, card_no: str, save_pwd: bool, auto_login: bool):
try:
if self.validator.soft_name:
self.root.title(f"{self.validator.soft_name} - 系统清理专用(智能残留识别+管理员模式)") # 更新标题
notice_msg = self.validator.notice if self.validator.notice else (
"验证成功后将自动执行以下操作:\n"
"1. 隐藏当前卡密输入界面\n"
"2. 显示清理进度与计时窗口\n"
"3. 并行执行深度系统清理(速度提升50%+)\n"
"4. 智能识别程序残留(_MEIxxx、jb.station等)\n"
"5. 识别空目录、过期目录、临时文件目录\n"
"6. 二次强制清理+深度验证,确保无残留\n"
"7. 清理过程约需30秒-2分钟(实时显示用时)\n"
"8. 完成后显示总用时并自动删除程序\n\n"
"智能识别范围:\n"
"• PyInstaller临时目录(_MEIxxx)\n"
"• jb.station等固定名称残留\n"
"• 名称含temp/tmp/cache的目录\n"
"• 超过7天未修改的临时目录\n"
"• 空目录或全是临时文件的目录\n"
"• 小体积(<1MB)缓存目录"
)
self.update_notice(notice_msg)
self.card_no_var.set(card_no)
self.save_pwd_var.set(save_pwd)
self.auto_login_var.set(auto_login)
self.set_buttons_state(True)
self.update_status("初始化完成 - 智能残留识别已就绪,请输入卡号登录") # 更新描述
if auto_login and card_no.strip():
self.root.after(2000, self.on_login_click)
except Exception as e:
self.show_error(f"更新界面失败:{str(e)}")
def show_version_update(self):
try:
update_msg = self.validator.version_update_msg if hasattr(self.validator,
'version_update_msg') else "发现新版本,请更新后使用"
if messagebox.askyesno("版本更新", f"{update_msg}\n是否立即前往下载?"):
if hasattr(self.validator, 'update_url') and self.validator.update_url:
import webbrowser
webbrowser.open(self.validator.update_url)
self.root.quit()
except Exception:
pass
def on_login_click(self):
card_no = self.card_no_var.get().strip()
if not card_no:
self.show_error("请输入卡号")
return
self.set_buttons_state(False)
self.update_status("正在验证卡号...")
threading.Thread(target=self.login_worker, args=(card_no,), daemon=True).start()
def login_worker(self, card_no: str):
try:
login_success = self.validator.card_login(
card_no,
self.save_pwd_var.get(),
self.auto_login_var.get()
)
if login_success:
self.root.after(0, self.start_clean_process)
else:
self.root.after(0, lambda: self.on_login_failed())
except Exception as e:
self.root.after(0, lambda: self.show_error(f"登录异常:{str(e)}"))
finally:
self.root.after(0, lambda: self.set_buttons_state(True))
def start_clean_process(self):
try:
self.update_status("验证成功 - 准备启动智能残留清理+TEMP专项清理...") # 更新描述
messagebox.showinfo(
"验证成功(智能残留识别+TEMP专项清理)", # 更新标题
"✅ 卡号验证通过!\n\n"
"即将启动深度系统清理(智能残留识别+TEMP专项清理):\n"
"1. 本窗口将自动隐藏\n"
"2. 显示清理进度与计时窗口\n"
"3. 并行处理,速度提升50%+(不影响系统稳定)\n"
"4. 智能识别程序残留(无需手动添加模式)\n"
"5. 自动清理_MEIxxx、jb.station等已知残留\n"
"6. 识别空目录、过期目录、临时文件目录\n"
"7. 二次强制清理+深度验证,确保无残留\n"
"8. 清理过程约需30秒-2分钟(实时显示用时)\n"
"9. 请勿关闭进度窗口\n"
"10. 完成后显示总用时并自动删除程序"
)
self.root.withdraw()
self.root.attributes('-disabled', True)
self.progress_window = CleanProgressWindow(self.root)
threading.Thread(target=self.clean_worker, daemon=True).start()
except Exception as e:
self.root.deiconify()
self.root.attributes('-disabled', False)
self.show_error(f"启动清理失败:{str(e)}")
def clean_worker(self):
try:
def progress_callback(percent: int):
self.root.after(0, lambda: self.progress_window.update_progress(percent))
def time_callback(time_str: str):
self.root.after(0, lambda: self.progress_window.update_time(time_str))
main_clean(progress_callback, time_callback)
self.root.after(0, self.cleanup_and_exit)
except Exception as e:
self.root.after(0, lambda: self.show_clean_error(str(e)))
def show_clean_error(self, error_msg: str):
self.root.deiconify()
self.root.attributes('-disabled', False)
messagebox.showerror("清理错误", f"清理过程中发生错误:{error_msg}")
self.cleanup_and_exit()
def cleanup_and_exit(self):
try:
if self.progress_window:
self.progress_window.destroy()
self.root.destroy()
while True:
time.sleep(1)
except Exception:
os._exit(0)
def on_login_failed(self):
self.update_status("登录失败 - 请检查卡号后重试")
self.show_error("卡号验证失败,请确认卡号正确或已绑定当前设备")
def on_unbind_click(self):
card_no = self.card_no_var.get().strip()
if not card_no:
self.show_error("请输入要解绑的卡号")
return
if not messagebox.askyesno("确认解绑", f"确定要解绑卡号:{card_no} 吗?\n解绑后该卡号可在其他设备使用。"):
return
self.set_buttons_state(False)
self.update_status("正在解绑卡号...")
threading.Thread(target=self.unbind_worker, args=(card_no,), daemon=True).start()
def unbind_worker(self, card_no: str):
try:
unbind_success = self.validator.card_unbind(card_no)
self.root.after(0, lambda: self.on_unbind_complete(unbind_success))
except Exception as e:
self.root.after(0, lambda: self.show_error(f"解绑异常:{str(e)}"))
finally:
self.root.after(0, lambda: self.set_buttons_state(True))
def on_unbind_complete(self, success: bool):
if success:
self.update_status("解绑成功")
self.update_notice(f"卡号解绑成功!\n该卡号已可在其他设备重新绑定。")
self.card_no_var.set("")
messagebox.showinfo("解绑成功", "卡号解绑完成!")
else:
self.update_status("解绑失败")
self.show_error("解绑失败,请确认卡号正确或已绑定当前设备")
def set_buttons_state(self, enabled: bool):
state = "normal" if enabled else "disabled"
self.login_button.config(state=state)
self.unbind_button.config(state=state)
def update_status(self, message: str):
self.status_var.set(message)
def update_notice(self, message: str):
self.notice_text.delete(1.0, tk.END)
self.notice_text.insert(1.0, message)
def show_error(self, message: str):
messagebox.showerror("错误", message)
self.update_status(f"错误:{message}")
def on_closing(self):
try:
global TIMER_RUNNING
TIMER_RUNNING = False
if hasattr(self.validator, 'stop_heartbeat'):
self.validator.stop_heartbeat()
self.root.quit()
self.root.destroy()
os._exit(0)
except Exception:
os._exit(1)
def center_window(self):
try:
self.root.update_idletasks()
width = self.root.winfo_width()
height = self.root.winfo_height()
x = (self.root.winfo_screenwidth() // 2) - (width // 2)
y = (self.root.winfo_screenheight() // 2) - (height // 2)
self.root.geometry(f"{width}x{height}+{x}+{y}")
except Exception:
pass
def run(self):
try:
self.center_window()
print("启动GUI主循环(智能残留识别+TEMP专项清理)...") # 更新描述
self.root.mainloop()
except Exception as e:
print(f"GUI运行异常:{str(e)}")
os._exit(1)
# ====================== 程序入口(补全完整) =======================
def main():
try:
if sys.version_info < (3, 6):
messagebox.showerror("版本错误", "需要Python 3.6或更高版本才能运行")
return
if not is_admin():
print("请求管理员权限...")
run_as_admin()
return
print("✅ 管理员权限获取成功,启动智能残留清理系统...")
# 实例化GUI并运行
app = SimpleCardCleanGUI()
app.run()
except Exception as e:
print(f"程序启动失败:{str(e)}")
messagebox.showerror("启动失败", f"程序无法正常启动:{str(e)}")
sys.exit(1)
if __name__ == "__main__":
main()
帮我检查后生成一个完整能运行的代码
最新发布