在IE8下的target="_self"问题,我以前问的,原因找到

本文讨论了使用showModalDialog方法在不同浏览器中弹出窗口的行为差异,特别是IE8与IE6之间的区别。作者提到通过调整<basetarget='_self'>的位置来解决问题。
原贴是这样的
问题是这样的
我在A窗口用showModalDialog方法弹出一个新窗口B,
但单击新窗口B中的按钮后,IE8下又会弹出一个新窗口,但IE6下不会。
因为我加了 <base target="_self">
这行代码。
难道IE8下,这个语句没有用?
IE6下是可以的。
求解。 
解决方法:
问题源头解决了
将<base target="_self" />
这一段放到<title></title>的下面,放在其它地方不行。
""" mlperf inference benchmarking tool """ from __future__ import division from __future__ import print_function from __future__ import unicode_literals # from memory_profiler import profile import argparse import array import collections import json import logging import os import sys import threading import time from multiprocessing import JoinableQueue import sklearn import star_loadgen as lg import numpy as np from mindspore import context from mindspore.train.model import Model from mindspore.train.serialization import load_checkpoint, load_param_into_net from src.model_utils.device_adapter import get_device_num, get_rank_id,get_device_id import os from mindspore import Model, context from mindspore.train.serialization import load_checkpoint, load_param_into_net,\ build_searched_strategy, merge_sliced_parameter from src.wide_and_deep import PredictWithSigmoid, TrainStepWrap, NetWithLossClass, WideDeepModel from src.callbacks import LossCallBack from src.datasets import create_dataset, DataType from src.metrics import AUCMetric from src.model_utils.moxing_adapter import moxing_wrapper from src.metrics import AUCMetric from src.callbacks import EvalCallBack import src.wide_and_deep as wide_deep import src.datasets as datasets from src.model_utils.config import config # from pygcbs_client.task import Task # task = Task() # config = task.config context.set_context(mode=context.GRAPH_MODE, device_target=config.device_target , device_id = 1) print(config.device_id) batch_size = config.batch_size def add_write(file_path, print_str): with open(file_path, 'a+', encoding='utf-8') as file_out: file_out.write(print_str + '\n') def get_WideDeep_net(config): """ Get network of wide&deep model. """ WideDeep_net = WideDeepModel(config) loss_net = NetWithLossClass(WideDeep_net, config) train_net = TrainStepWrap(loss_net) eval_net = PredictWithSigmoid(WideDeep_net) return train_net, eval_net class ModelBuilder(): """ Wide and deep model builder """ def __init__(self): pass def get_hook(self): pass def get_train_hook(self): hooks = [] callback = LossCallBack() hooks.append(callback) if int(os.getenv('DEVICE_ID')) == 0: pass return hooks def get_net(self, config): return get_WideDeep_net(config) logging.basicConfig(level=logging.INFO) log = logging.getLogger("main") NANO_SEC = 1e9 MILLI_SEC = 1000 # pylint: disable=missing-docstring # the datasets we support SUPPORTED_DATASETS = { "debug": (datasets.Dataset, wide_deep.pre_process_criteo_wide_deep, wide_deep.WideDeepPostProcess(), {"randomize": 'total', "memory_map": True}), "multihot-criteo-sample": (wide_deep.WideDeepModel, wide_deep.pre_process_criteo_wide_deep, wide_deep.WideDeepPostProcess(), {"randomize": 'total', "memory_map": True}), "kaggle-criteo": (wide_deep.WideDeepModel, wide_deep.pre_process_criteo_wide_deep, wide_deep.WideDeepPostProcess(), {"randomize": 'total', "memory_map": True}), } # pre-defined command line options so simplify things. They are used as defaults and can be # overwritten from command line SUPPORTED_PROFILES = { "defaults": { "dataset": "multihot-criteo", "inputs": "continuous and categorical features", "outputs": "probability", "backend": "mindspore-native", "model": "wide_deep", "max-batchsize": 2048, }, "dlrm-debug-mindspore": { "dataset": "debug", "inputs": "continuous and categorical features", "outputs": "probability", "backend": "pytorch-native", "model": "dlrm", "max-batchsize": 128, }, "dlrm-multihot-sample-mindspore": { "dataset": "multihot-criteo-sample", "inputs": "continuous and categorical features", "outputs": "probability", "backend": "pytorch-native", "model": "dlrm", "max-batchsize": 2048, }, "dlrm-multihot-mindspore": { "dataset": "multihot-criteo", "inputs": "continuous and categorical features", "outputs": "probability", "backend": "pytorch-native", "model": "dlrm", "max-batchsize": 2048, } } SCENARIO_MAP = { "SingleStream": lg.TestScenario.SingleStream, "MultiStream": lg.TestScenario.MultiStream, "Server": lg.TestScenario.Server, "Offline": lg.TestScenario.Offline, } last_timeing = [] import copy class Item: """An item that we queue for processing by the thread pool.""" def __init__(self, query_id, content_id, features, batch_T=None, idx_offsets=None): self.query_id = query_id self.content_id = content_id self.data = features self.batch_T = batch_T self.idx_offsets = idx_offsets self.start = time.time() import mindspore.dataset as mds lock = threading.Lock() class RunnerBase: def __init__(self, model, ds, threads, post_proc=None): self.take_accuracy = False self.ds = ds self.model = model self.post_process = post_proc self.threads = threads self.result_timing = [] def handle_tasks(self, tasks_queue): pass def start_run(self, result_dict, take_accuracy): self.result_dict = result_dict self.result_timing = [] self.take_accuracy = take_accuracy self.post_process.start() def run_one_item(self, qitem): # run the prediction processed_results = [] try: lock.acquire() data = datasets._get_mindrecord_dataset(*qitem.data) t1 = time.time() results = self.model.eval(data) self.result_timing.append(time.time() - t1) print('##################',time.time()) lock.release() processed_results = self.post_process(results, qitem.batch_T, self.result_dict) # self.post_process.add_results(, ) # g_lables.extend(self.model.auc_metric.true_labels) # g_predicts.extend(self.model.auc_metric.pred_probs) g_lables.extend(self.model.auc_metric.true_labels) g_predicts.extend(self.model.auc_metric.pred_probs) except Exception as ex: # pylint: disable=broad-except log.error("thread: failed, %s", ex) # since post_process will not run, fake empty responses processed_results = [[]] * len(qitem.query_id) finally: response_array_refs = [] response = [] for idx, query_id in enumerate(qitem.query_id): # NOTE: processed_results returned by DlrmPostProcess store both # result = processed_results[idx][0] and target = processed_results[idx][1] # also each idx might be a query of samples, rather than a single sample # depending on the --samples-to-aggregate* arguments. # debug prints # print("s,e:",s_idx,e_idx, len(processed_results)) response_array = array.array("B", np.array(processed_results[0:1], np.float32).tobytes()) response_array_refs.append(response_array) bi = response_array.buffer_info() response.append(lg.QuerySampleResponse(query_id, bi[0], bi[1])) lg.QuerySamplesComplete(response) def enqueue(self, query_samples): idx = [q.index for q in query_samples] query_id = [q.id for q in query_samples] # print(idx) query_len = len(query_samples) # if query_len < self.max_batchsize: # samples = self.ds.get_samples(idx) # # batch_T = [self.ds.get_labels(sample) for sample in samples] # self.run_one_item(Item(query_id, idx, samples)) # else: bs = 1 for i in range(0, query_len, bs): ie = min(i + bs, query_len) samples = self.ds.get_samples(idx[i:ie]) # batch_T = [self.ds.get_labels(sample) for sample in samples] self.run_one_item(Item(query_id[i:ie], idx[i:ie], samples)) def finish(self): pass import threading class MyQueue: def __init__(self, *args, **kwargs): self.lock = threading.Lock() self._data = [] self.status = True def put(self, value): # self.lock.acquire() self._data.append(value) # self.lock.release() def get(self): if self.status and self._data: return self._data.pop(0) if self.status: while self._data: time.sleep(0.1) return self._data.pop(0) return None # self.lock.acquire() # return self._data.pop(0) # self.lock.release() def task_done(self, *args, **kwargs): self.status = False class QueueRunner(RunnerBase): def __init__(self, model, ds, threads, post_proc=None): super().__init__(model, ds, threads, post_proc) queue_size_multiplier = 4 # (args.samples_per_query_offline + max_batchsize - 1) // max_batchsize) self.tasks = JoinableQueue(maxsize=threads * queue_size_multiplier) self.workers = [] self.result_dict = {} for _ in range(self.threads): worker = threading.Thread(target=self.handle_tasks, args=(self.tasks,)) worker.daemon = True self.workers.append(worker) worker.start() def handle_tasks(self, tasks_queue): """Worker thread.""" while True: qitem = tasks_queue.get() if qitem is None: # None in the queue indicates the parent want us to exit tasks_queue.task_done() break self.run_one_item(qitem) tasks_queue.task_done() def enqueue(self, query_samples): idx = [q.index for q in query_samples] query_id = [q.id for q in query_samples] query_len = len(query_samples) # print(idx) # if query_len < self.max_batchsize: # samples = self.ds.get_samples(idx) # # batch_T = [self.ds.get_labels(sample) for sample in samples] # data = Item(query_id, idx, samples) # self.tasks.put(data) # else: bs = 1 for i in range(0, query_len, bs): ie = min(i + bs, query_len) samples = self.ds.get_samples(idx) # batch_T = [self.ds.get_labels(sample) for sample in samples] self.tasks.put(Item(query_id[i:ie], idx[i:ie], samples)) def finish(self): # exit all threads for _ in self.workers: self.tasks.put(None) for worker in self.workers: worker.join() def add_results(final_results, name, result_dict, result_list, took, show_accuracy=False): percentiles = [50., 80., 90., 95., 99., 99.9] buckets = np.percentile(result_list, percentiles).tolist() buckets_str = ",".join(["{}:{:.4f}".format(p, b) for p, b in zip(percentiles, buckets)]) if result_dict["total"] == 0: result_dict["total"] = len(result_list) # this is what we record for each run result = { "took": took, "mean": np.mean(result_list), "percentiles": {str(k): v for k, v in zip(percentiles, buckets)}, "qps": len(result_list) / took, "count": len(result_list), "good_items": result_dict["good"], "total_items": result_dict["total"], } acc_str = "" if show_accuracy: result["accuracy"] = 100. * result_dict["good"] / result_dict["total"] acc_str = ", acc={:.3f}%".format(result["accuracy"]) if "roc_auc" in result_dict: result["roc_auc"] = 100. * result_dict["roc_auc"] acc_str += ", auc={:.3f}%".format(result["roc_auc"]) # add the result to the result dict final_results[name] = result # to stdout print("{} qps={:.2f}, mean={:.4f}, time={:.3f}{}, queries={}, tiles={}".format( name, result["qps"], result["mean"], took, acc_str, len(result_list), buckets_str)) lock = threading.Lock() def append_file(file_path, data): with lock: my_string = ','.join(str(f) for f in data) with open(file_path, 'a+') as file: file.write(my_string + '\n') def read_file(file_path): lines_as_lists = [] with open(file_path, 'r') as file: for line in file: # 去除行尾的换行符,并将行分割成列表 lines_as_lists.extend([float(num) for num in line.strip().split(',')]) return lines_as_lists def get_score(model, quality: float, performance: float): print(model, quality,performance) try: score =0 if model["scenario"] == 'SingleStream'or model["scenario"]== 'MultiStream': if quality >= model["accuracy"]: score = model["baseline_performance"] / (performance + 1e-9) * model["base_score"] else: score ==0 elif model["scenario"]== 'Server' or model["scenario"] == 'Offline': if quality >= model["accuracy"]: score = performance * model["base_score"] / model["baseline_performance"] print(model["baseline_performance"]) else: score ==0 except Exception as e: score ==0 finally: return score def main(): global last_timeing # 初始化时清空文件 global g_lables global g_predicts # args = get_args() g_lables=[] g_predicts=[] # # dataset to use wanted_dataset, pre_proc, post_proc, kwargs = SUPPORTED_DATASETS["debug"] # # --count-samples can be used to limit the number of samples used for testing ds = wanted_dataset(directory=config.dataset_path, train_mode=False, epochs=15, line_per_sample=1000, batch_size=config.test_batch_size, data_type=DataType.MINDRECORD,total_size = config.total_size) # # load model to backend # model = backend.load(args.model_path, inputs=args.inputs, outputs=args.outputs) net_builder = ModelBuilder() train_net, eval_net = net_builder.get_net(config) # ckpt_path = config.ckpt_path param_dict = load_checkpoint(config.ckpt_path) load_param_into_net(eval_net, param_dict) train_net.set_train() eval_net.set_train(False) # acc_metric = AccMetric() # model = Model(train_net, eval_network=eval_net, metrics={"acc": acc_metric}) auc_metric1 = AUCMetric() model = Model(train_net, eval_network=eval_net, metrics={"auc": auc_metric1}) model.auc_metric = auc_metric1 # res = model.eval(ds_eval) final_results = { "runtime": "wide_deep_mindspore", "version": "v2", "time": int(time.time()), "cmdline": str(config), } mlperf_conf = os.path.abspath(config.mlperf_conf) if not os.path.exists(mlperf_conf): log.error("{} not found".format(mlperf_conf)) sys.exit(1) user_conf = os.path.abspath(config.user_conf) if not os.path.exists(user_conf): log.error("{} not found".format(user_conf)) sys.exit(1) if config.output: output_dir = os.path.abspath(config.output) os.makedirs(output_dir, exist_ok=True) os.chdir(output_dir) # # make one pass over the dataset to validate accuracy # count = ds.get_item_count() count = 5 base_score = config.config.base_score #task. accuracy = config.config.accuracy #task. baseline_performance = config.baseline_performance scenario_str = config["scenario"] #task. scenario = SCENARIO_MAP[scenario_str] runner_map = { lg.TestScenario.SingleStream: RunnerBase, lg.TestScenario.MultiStream: QueueRunner, lg.TestScenario.Server: QueueRunner, lg.TestScenario.Offline: QueueRunner } runner = runner_map[scenario](model, ds, config.threads_count, post_proc=post_proc) def issue_queries(query_samples): runner.enqueue(query_samples) def flush_queries(): pass settings = lg.TestSettings() settings.FromConfig(mlperf_conf, config.model_path, config.scenario) settings.FromConfig(user_conf, config.model_path, config.scenario) settings.scenario = scenario settings.mode = lg.TestMode.AccuracyOnly sut = lg.ConstructSUT(issue_queries, flush_queries) qsl = lg.ConstructQSL(count, config.performance_count, ds.load_query_samples, ds.unload_query_samples) log.info("starting {}".format(scenario)) result_dict = {"good": 0, "total": 0, "roc_auc": 0, "scenario": str(scenario)} runner.start_run(result_dict, config.accuracy) lg.StartTest(sut, qsl, settings) result_dict["good"] = runner.post_process.good result_dict["total"] = runner.post_process.total last_timeing = runner.result_timing post_proc.finalize(result_dict) add_results(final_results, "{}".format(scenario), result_dict, last_timeing, time.time() - ds.last_loaded, config.accuracy) runner.finish() lg.DestroyQSL(qsl) lg.DestroySUT(sut) # If multiple subprocesses are running the model send a signal to stop them if (int(os.environ.get("WORLD_SIZE", 1)) > 1): model.eval(None) from sklearn.metrics import roc_auc_score # labels = read_file(labels_path) # predicts = read_file(predicts_path) final_results['auc'] = sklearn.metrics.roc_auc_score(g_lables, g_predicts) print("auc+++++", final_results['auc']) NormMetric= { 'scenario': scenario_str, 'accuracy': accuracy, 'baseline_performance': baseline_performance, 'performance_unit': 's', 'base_score': base_score } # 打开文件 reprot_array=[] test_suit_array=[] test_suit_obj={} test_cases_array=[] test_cases_obj={} test_cases_obj["Name"] = config["task_name"] test_cases_obj["Performance Unit"] = config["performance_unit"] test_cases_obj["Total Duration"] = time.time() - ds.last_loaded test_cases_obj["Train Duration"] = None test_cases_obj["Training Info"] = { "Real Quality" :None, "Learning Rate" :None, "Base Quality" :None, "Epochs" :None, "Optimizer" :None } test_cases_obj["Software Versions"] = { "Python" :3.8, "Framework" :"Mindspore 2.2.14" } percentiles = [50., 80., 90., 95., 99., 99.9] buckets = np.percentile(last_timeing, percentiles).tolist() took = time.time() - ds.last_loaded qps = len(last_timeing) / took print(buckets) if scenario_str=="SingleStream": test_cases_obj["Performance Metric"] = buckets[2] if scenario_str=="MultiStream": test_cases_obj["Performance Metric"] = buckets[4] if scenario_str=="Server": test_cases_obj["Performance Metric"] = qps if scenario_str=="Offline": test_cases_obj["Performance Metric"] = qps score = get_score(NormMetric, final_results["auc"], test_cases_obj["Performance Metric"]) test_cases_obj["Score"] = score test_cases_array.append(test_cases_obj) test_suit_obj["Test Cases"] = test_cases_array test_suit_obj["Name"] = "Inference Suite" test_suit_array.append(test_suit_obj) test_obj = {"Test Suites": test_suit_array} reprot_array.append(test_obj) test_suit_result_obj = {"Name":"Inference Suite","Description":"inference model","Score":score } test_suit_result_array = [] test_suit_result_array.append(test_suit_result_obj) test_suit_result_obj1 = {"Test Suites Results":test_suit_result_array} reprot_array.append(test_suit_result_obj1) epoch_obj={ "epoch":None, "epoch_time":None, "train_loss":None, "metric":None, "metric_name":None } reprot_array.append(epoch_obj) result_final = {"Report Info": reprot_array } print("result_final", result_final) # task.save(result_final) if __name__ == "__main__": # try: # if task.config["is_run_infer"] == True: # main() # task.close() # else: # task.close() # raise ValueError # except Exception as e: # task.logger.error(e) # task.close(e) # task.logger.info("Finish ") # if task.config["is_run_infer"] == True: # print(config) main() # task.close()介绍一下这段代码
06-17
# -*- coding:utf-8 -*- # zlgcan.py # # ~~~~~~~~~~~~ # # ZLGCAN API # # ~~~~~~~~~~~~ # # ------------------------------------------------------------------ # Language: Python 2.7, 3.6 # ------------------------------------------------------------------ # from ctypes import * import platform import threading import time ZCAN_DEVICE_TYPE = c_uint INVALID_DEVICE_HANDLE = 0 INVALID_CHANNEL_HANDLE = 0 ''' Device Type ''' ZCAN_PCI5121 = ZCAN_DEVICE_TYPE(1) ZCAN_PCI9810 = ZCAN_DEVICE_TYPE(2) ZCAN_USBCAN1 = ZCAN_DEVICE_TYPE(3) ZCAN_USBCAN2 = ZCAN_DEVICE_TYPE(4) ZCAN_PCI9820 = ZCAN_DEVICE_TYPE(5) ZCAN_CAN232 = ZCAN_DEVICE_TYPE(6) ZCAN_PCI5110 = ZCAN_DEVICE_TYPE(7) ZCAN_CANLITE = ZCAN_DEVICE_TYPE(8) ZCAN_ISA9620 = ZCAN_DEVICE_TYPE(9) ZCAN_ISA5420 = ZCAN_DEVICE_TYPE(10) ZCAN_PC104CAN = ZCAN_DEVICE_TYPE(11) ZCAN_CANETUDP = ZCAN_DEVICE_TYPE(12) ZCAN_CANETE = ZCAN_DEVICE_TYPE(12) ZCAN_DNP9810 = ZCAN_DEVICE_TYPE(13) ZCAN_PCI9840 = ZCAN_DEVICE_TYPE(14) ZCAN_PC104CAN2 = ZCAN_DEVICE_TYPE(15) ZCAN_PCI9820I = ZCAN_DEVICE_TYPE(16) ZCAN_CANETTCP = ZCAN_DEVICE_TYPE(17) ZCAN_PCIE_9220 = ZCAN_DEVICE_TYPE(18) ZCAN_PCI5010U = ZCAN_DEVICE_TYPE(19) ZCAN_USBCAN_E_U = ZCAN_DEVICE_TYPE(20) ZCAN_USBCAN_2E_U = ZCAN_DEVICE_TYPE(21) ZCAN_PCI5020U = ZCAN_DEVICE_TYPE(22) ZCAN_EG20T_CAN = ZCAN_DEVICE_TYPE(23) ZCAN_PCIE9221 = ZCAN_DEVICE_TYPE(24) ZCAN_WIFICAN_TCP = ZCAN_DEVICE_TYPE(25) ZCAN_WIFICAN_UDP = ZCAN_DEVICE_TYPE(26) ZCAN_PCIe9120 = ZCAN_DEVICE_TYPE(27) ZCAN_PCIe9110 = ZCAN_DEVICE_TYPE(28) ZCAN_PCIe9140 = ZCAN_DEVICE_TYPE(29) ZCAN_USBCAN_4E_U = ZCAN_DEVICE_TYPE(31) ZCAN_CANDTU_200UR = ZCAN_DEVICE_TYPE(32) ZCAN_CANDTU_MINI = ZCAN_DEVICE_TYPE(33) ZCAN_USBCAN_8E_U = ZCAN_DEVICE_TYPE(34) ZCAN_CANREPLAY = ZCAN_DEVICE_TYPE(35) ZCAN_CANDTU_NET = ZCAN_DEVICE_TYPE(36) ZCAN_CANDTU_100UR = ZCAN_DEVICE_TYPE(37) ZCAN_PCIE_CANFD_100U = ZCAN_DEVICE_TYPE(38) ZCAN_PCIE_CANFD_200U = ZCAN_DEVICE_TYPE(39) ZCAN_PCIE_CANFD_400U = ZCAN_DEVICE_TYPE(40) ZCAN_USBCANFD_200U = ZCAN_DEVICE_TYPE(41) ZCAN_USBCANFD_100U = ZCAN_DEVICE_TYPE(42) ZCAN_USBCANFD_MINI = ZCAN_DEVICE_TYPE(43) ZCAN_CANFDCOM_100IE = ZCAN_DEVICE_TYPE(44) ZCAN_CANSCOPE = ZCAN_DEVICE_TYPE(45) ZCAN_CLOUD = ZCAN_DEVICE_TYPE(46) ZCAN_CANDTU_NET_400 = ZCAN_DEVICE_TYPE(47) ZCAN_CANFDNET_200U_TCP = ZCAN_DEVICE_TYPE(48) ZCAN_CANFDNET_200U_UDP = ZCAN_DEVICE_TYPE(49) ZCAN_CANFDWIFI_100U_TCP = ZCAN_DEVICE_TYPE(50) ZCAN_CANFDWIFI_100U_UDP = ZCAN_DEVICE_TYPE(51) ZCAN_CANFDNET_400U_TCP = ZCAN_DEVICE_TYPE(52) ZCAN_CANFDNET_400U_UDP = ZCAN_DEVICE_TYPE(53) ZCAN_CANFDBLUE_200U = ZCAN_DEVICE_TYPE(54) ZCAN_CANFDNET_100U_TCP = ZCAN_DEVICE_TYPE(55) ZCAN_CANFDNET_100U_UDP = ZCAN_DEVICE_TYPE(56) ZCAN_CANFDNET_800U_TCP = ZCAN_DEVICE_TYPE(57) ZCAN_CANFDNET_800U_UDP = ZCAN_DEVICE_TYPE(58) ZCAN_USBCANFD_800U = ZCAN_DEVICE_TYPE(59) ZCAN_PCIE_CANFD_100U_EX = ZCAN_DEVICE_TYPE(60) ZCAN_PCIE_CANFD_400U_EX = ZCAN_DEVICE_TYPE(61) ZCAN_PCIE_CANFD_200U_MINI = ZCAN_DEVICE_TYPE(62) ZCAN_PCIE_CANFD_200U_M2 = ZCAN_DEVICE_TYPE(63) ZCAN_PCIE_CANFD_200U_EX = ZCAN_DEVICE_TYPE(62) ZCAN_CANFDDTU_400_TCP = ZCAN_DEVICE_TYPE(64) ZCAN_CANFDDTU_400_UDP = ZCAN_DEVICE_TYPE(65) ZCAN_CANFDWIFI_200U_TCP = ZCAN_DEVICE_TYPE(66) ZCAN_CANFDWIFI_200U_UDP = ZCAN_DEVICE_TYPE(67) ZCAN_CANFDDTU_800ER_TCP = ZCAN_DEVICE_TYPE(68) ZCAN_CANFDDTU_800ER_UDP = ZCAN_DEVICE_TYPE(69) ZCAN_CANFDDTU_800EWGR_TCP = ZCAN_DEVICE_TYPE(70) ZCAN_CANFDDTU_800EWGR_UDP = ZCAN_DEVICE_TYPE(71) ZCAN_CANFDDTU_600EWGR_TCP = ZCAN_DEVICE_TYPE(72) ZCAN_CANFDDTU_600EWGR_UDP = ZCAN_DEVICE_TYPE(73) ZCAN_CANFDDTU_CASCADE_TCP = ZCAN_DEVICE_TYPE(74) ZCAN_CANFDDTU_CASCADE_UDP = ZCAN_DEVICE_TYPE(75) ZCAN_USBCANFD_400U = ZCAN_DEVICE_TYPE(76) ZCAN_CANFDDTU_200U = ZCAN_DEVICE_TYPE(77) ZCAN_CANFDBRIDGE_PLUS = ZCAN_DEVICE_TYPE(80) ZCAN_CANFDDTU_300U = ZCAN_DEVICE_TYPE(81) ZCAN_VIRTUAL_DEVICE = ZCAN_DEVICE_TYPE(99) ''' Interface return status ''' ZCAN_STATUS_ERR = 0 ZCAN_STATUS_OK = 1 ZCAN_STATUS_ONLINE = 2 ZCAN_STATUS_OFFLINE = 3 ZCAN_STATUS_UNSUPPORTED = 4 ''' CAN type ''' ZCAN_TYPE_CAN = c_uint(0) ZCAN_TYPE_CANFD = c_uint(1) def input_thread(): input() ''' Device information ''' class ZCAN_DEVICE_INFO(Structure): _fields_ = [("hw_Version", c_ushort), ("fw_Version", c_ushort), ("dr_Version", c_ushort), ("in_Version", c_ushort), ("irq_Num", c_ushort), ("can_Num", c_ubyte), ("str_Serial_Num", c_ubyte * 20), ("str_hw_Type", c_ubyte * 40), ("reserved", c_ushort * 4)] def __str__(self): return "Hardware Version:%s\nFirmware Version:%s\nDriver Interface:%s\nInterface Interface:%s\nInterrupt Number:%d\nCAN Number:%d\nSerial:%s\nHardware Type:%s\n" %( self.hw_version, self.fw_version, self.dr_version, self.in_version, self.irq_num, self.can_num, self.serial, self.hw_type) def _version(self, version): return ("V%02x.%02x" if version // 0xFF >= 9 else "V%d.%02x") % (version // 0xFF, version & 0xFF) @property def hw_version(self): return self._version(self.hw_Version) @property def fw_version(self): return self._version(self.fw_Version) @property def dr_version(self): return self._version(self.dr_Version) @property def in_version(self): return self._version(self.in_Version) @property def irq_num(self): return self.irq_Num @property def can_num(self): return self.can_Num @property def serial(self): serial = '' for c in self.str_Serial_Num: if c > 0: serial += chr(c) else: break return serial @property def hw_type(self): hw_type = '' for c in self.str_hw_Type: if c > 0: hw_type += chr(c) else: break return hw_type class _ZCAN_CHANNEL_CAN_INIT_CONFIG(Structure): _fields_ = [("acc_code", c_uint), ("acc_mask", c_uint), ("reserved", c_uint), ("filter", c_ubyte), ("timing0", c_ubyte), ("timing1", c_ubyte), ("mode", c_ubyte)] class _ZCAN_CHANNEL_CANFD_INIT_CONFIG(Structure): _fields_ = [("acc_code", c_uint), ("acc_mask", c_uint), ("abit_timing", c_uint), ("dbit_timing", c_uint), ("brp", c_uint), ("filter", c_ubyte), ("mode", c_ubyte), ("pad", c_ushort), ("reserved", c_uint)] class _ZCAN_CHANNEL_INIT_CONFIG(Union): _fields_ = [("can", _ZCAN_CHANNEL_CAN_INIT_CONFIG), ("canfd", _ZCAN_CHANNEL_CANFD_INIT_CONFIG)] class ZCAN_CHANNEL_INIT_CONFIG(Structure): _fields_ = [("can_type", c_uint), ("config", _ZCAN_CHANNEL_INIT_CONFIG)] class ZCAN_CHANNEL_ERR_INFO(Structure): _fields_ = [("error_code", c_uint), ("passive_ErrData", c_ubyte * 3), ("arLost_ErrData", c_ubyte)] class ZCAN_CHANNEL_STATUS(Structure): _fields_ = [("errInterrupt", c_ubyte), ("regMode", c_ubyte), ("regStatus", c_ubyte), ("regALCapture", c_ubyte), ("regECCapture", c_ubyte), ("regEWLimit", c_ubyte), ("regRECounter", c_ubyte), ("regTECounter", c_ubyte), ("Reserved", c_ubyte)] class ZCAN_CAN_FRAME(Structure): _fields_ = [("can_id", c_uint, 29), ("err", c_uint, 1), ("rtr", c_uint, 1), ("eff", c_uint, 1), ("can_dlc", c_ubyte), ("__pad", c_ubyte), ("__res0", c_ubyte), ("__res1", c_ubyte), ("data", c_ubyte * 8)] class ZCAN_CANFD_FRAME(Structure): _fields_ = [("can_id", c_uint, 29), ("err", c_uint, 1), ("rtr", c_uint, 1), ("eff", c_uint, 1), ("len", c_ubyte), ("brs", c_ubyte, 1), ("esi", c_ubyte, 1), ("__pad", c_ubyte, 6), ("__res0", c_ubyte), ("__res1", c_ubyte), ("data", c_ubyte * 64)] class ZCANdataFlag(Structure): _pack_ = 1 _fields_= [("frameType",c_uint,2), ("txDelay",c_uint,2), ("transmitType",c_uint,4), ("txEchoRequest",c_uint,1), ("txEchoed",c_uint,1), ("reserved",c_uint,22), ] class ZCANFDData(Structure): ##表示 CAN/CANFD 帧结构,目前仅作为 ZCANDataObj 结构的成员使用 _pack_ = 1 _fields_= [("timestamp",c_uint64), ("flag",ZCANdataFlag), ("extraData",c_ubyte*4), ("frame",ZCAN_CANFD_FRAME),] class ZCANDataObj(Structure): _pack_ = 1 _fields_= [("dataType",c_ubyte), ("chnl",c_ubyte), ("flag",c_ushort), ("extraData",c_ubyte*4), ("zcanfddata",ZCANFDData),##88个字节 ("reserved",c_ubyte*4), ] class ZCAN_Transmit_Data(Structure): _fields_ = [("frame", ZCAN_CAN_FRAME), ("transmit_type", c_uint)] class ZCAN_Receive_Data(Structure): _fields_ = [("frame", ZCAN_CAN_FRAME), ("timestamp", c_ulonglong)] class ZCAN_TransmitFD_Data(Structure): _fields_ = [("frame", ZCAN_CANFD_FRAME), ("transmit_type", c_uint)] class ZCAN_ReceiveFD_Data(Structure): _fields_ = [("frame", ZCAN_CANFD_FRAME), ("timestamp", c_ulonglong)] class ZCAN_AUTO_TRANSMIT_OBJ(Structure): _fields_ = [("enable", c_ushort), ("index", c_ushort), ("interval", c_uint), ("obj", ZCAN_Transmit_Data)] class ZCANFD_AUTO_TRANSMIT_OBJ(Structure): _fields_ = [("enable", c_ushort), ("index", c_ushort), ("interval", c_uint), ("obj", ZCAN_TransmitFD_Data)] class ZCANFD_AUTO_TRANSMIT_OBJ_PARAM(Structure): #auto_send delay _fields_ = [("indix", c_ushort), ("type", c_ushort), ("value", c_uint)] class IProperty(Structure): _fields_ = [("SetValue", c_void_p), ("GetValue", c_void_p), ("GetPropertys", c_void_p)] class ZCAN(object): def __init__(self): if platform.system() == "Windows": self.__dll = windll.LoadLibrary("./zlgcan.dll") else: print("No support now!") if self.__dll == None: print("DLL couldn't be loaded!") def OpenDevice(self, device_type, device_index, reserved): try: return self.__dll.ZCAN_OpenDevice(device_type, device_index, reserved) except: print("Exception on OpenDevice!") raise def CloseDevice(self, device_handle): try: return self.__dll.ZCAN_CloseDevice(device_handle) except: print("Exception on CloseDevice!") raise def GetDeviceInf(self, device_handle): try: info = ZCAN_DEVICE_INFO() ret = self.__dll.ZCAN_GetDeviceInf(device_handle, byref(info)) return info if ret == ZCAN_STATUS_OK else None except: print("Exception on ZCAN_GetDeviceInf") raise def DeviceOnLine(self, device_handle): try: return self.__dll.ZCAN_IsDeviceOnLine(device_handle) except: print("Exception on ZCAN_ZCAN_IsDeviceOnLine!") raise def InitCAN(self, device_handle, can_index, init_config): try: return self.__dll.ZCAN_InitCAN(device_handle, can_index, byref(init_config)) except: print("Exception on ZCAN_InitCAN!") raise def StartCAN(self, chn_handle): try: return self.__dll.ZCAN_StartCAN(chn_handle) except: print("Exception on ZCAN_StartCAN!") raise def ResetCAN(self, chn_handle): try: return self.__dll.ZCAN_ResetCAN(chn_handle) except: print("Exception on ZCAN_ResetCAN!") raise def ClearBuffer(self, chn_handle): try: return self.__dll.ZCAN_ClearBuffer(chn_handle) except: print("Exception on ZCAN_ClearBuffer!") raise def ReadChannelErrInfo(self, chn_handle): try: ErrInfo = ZCAN_CHANNEL_ERR_INFO() ret = self.__dll.ZCAN_ReadChannelErrInfo(chn_handle, byref(ErrInfo)) return ErrInfo if ret == ZCAN_STATUS_OK else None except: print("Exception on ZCAN_ReadChannelErrInfo!") raise def ReadChannelStatus(self, chn_handle): try: status = ZCAN_CHANNEL_STATUS() ret = self.__dll.ZCAN_ReadChannelStatus(chn_handle, byref(status)) return status if ret == ZCAN_STATUS_OK else None except: print("Exception on ZCAN_ReadChannelStatus!") raise def GetReceiveNum(self, chn_handle, can_type = ZCAN_TYPE_CAN): try: return self.__dll.ZCAN_GetReceiveNum(chn_handle, can_type) except: print("Exception on ZCAN_GetReceiveNum!") raise def Transmit(self, chn_handle, std_msg, len): try: return self.__dll.ZCAN_Transmit(chn_handle, byref(std_msg), len) except: print("Exception on ZCAN_Transmit!") raise def Receive(self, chn_handle, rcv_num, wait_time = c_int(-1)): try: rcv_can_msgs = (ZCAN_Receive_Data * rcv_num)() ret = self.__dll.ZCAN_Receive(chn_handle, byref(rcv_can_msgs), rcv_num, wait_time) return rcv_can_msgs, ret except: print("Exception on ZCAN_Receive!") raise def TransmitFD(self, chn_handle, fd_msg, len): try: return self.__dll.ZCAN_TransmitFD(chn_handle, byref(fd_msg), len) except: print("Exception on ZCAN_TransmitFD!") raise def TransmitData(self,device_handle,msg,len): try: return self.__dll.ZCAN_TransmitData(device_handle,byref(msg),len) except: print("Exception on ZCAN_TransmitData!") raise def ReceiveFD(self, chn_handle, rcv_num, wait_time = c_int(-1)): try: rcv_canfd_msgs = (ZCAN_ReceiveFD_Data * rcv_num)() ret = self.__dll.ZCAN_ReceiveFD(chn_handle, byref(rcv_canfd_msgs), rcv_num, wait_time) return rcv_canfd_msgs, ret except: print("Exception on ZCAN_ReceiveF D!") raise def ReceiveData(self,device_handle,rcv_num,wait_time = c_int(-1)): try: rcv_can_data_msgs = (ZCANDataObj * rcv_num)() ret = self.__dll.ZCAN_ReceiveData(device_handle , rcv_can_data_msgs, rcv_num,wait_time) return rcv_can_data_msgs ,ret except: print("Exception on ZCAN_ReceiveData!") raise def GetIProperty(self, device_handle): try: self.__dll.GetIProperty.restype = POINTER(IProperty) return self.__dll.GetIProperty(device_handle) except: print("Exception on ZCAN_GetIProperty!") raise def SetValue(self, iproperty, path, value): try: func = CFUNCTYPE(c_uint, c_char_p, c_char_p)(iproperty.contents.SetValue) return func(c_char_p(path.encode("utf-8")), c_char_p(value.encode("utf-8"))) except: print("Exception on IProperty SetValue") raise def SetValue1(self, iproperty, path, value): ############################# try: func = CFUNCTYPE(c_uint, c_char_p, c_char_p)(iproperty.contents.SetValue) return func(c_char_p(path.encode("utf-8")), c_void_p(value)) except: print("Exception on IProperty SetValue") raise def GetValue(self, iproperty, path): try: func = CFUNCTYPE(c_char_p, c_char_p)(iproperty.contents.GetValue) return func(c_char_p(path.encode("utf-8"))) except: print("Exception on IProperty GetValue") raise def ReleaseIProperty(self, iproperty): try: return self.__dll.ReleaseIProperty(iproperty) except: print("Exception on ZCAN_ReleaseIProperty!") raise def ZCAN_SetValue(self,device_handle,path,value): try: self.__dll.ZCAN_SetValue.argtypes=[c_void_p,c_char_p,c_void_p] return self.__dll.ZCAN_SetValue(device_handle,path.encode("utf-8"),value) except: print("Exception on ZCAN_SetValue") raise def ZCAN_GetValue(self,device_handle,path): try: self.__dll.ZCAN_GetValue.argtypes =[c_void_p,c_char_p] self.__dll.ZCAN_GetValue.restype =c_void_p return self.__dll.ZCAN_GetValue(device_handle,path.encode("utf-8")) except: print("Exception on ZCAN_GetValue") raise ############################################################################### ''' USBCANFD-MINI Demo ''' def canfd_start(zcanlib, device_handle, chn): ret = zcanlib.ZCAN_SetValue(device_handle, str(chn) + "/canfd_standard", "0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d CANFD standard failed!" %(chn)) ret = zcanlib.ZCAN_SetValue(device_handle, str(chn) + "/initenal_resistance", "1".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Open CH%d resistance failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/canfd_abit_baud_rate","500000".encode("utf-8")) #设置波特率 ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/canfd_dbit_baud_rate","2000000".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d baud failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle, "0/set_cn","A001".encode("utf-8")) if ret == ZCAN_STATUS_OK: t = zcanlib.ZCAN_GetValue(device_handle, "0/get_cn/1") print(c_char_p(t).value.decode("utf-8")) chn_init_cfg = ZCAN_CHANNEL_INIT_CONFIG() chn_init_cfg.can_type = ZCAN_TYPE_CANFD chn_init_cfg.config.canfd.mode = 0 chn_handle = zcanlib.InitCAN(device_handle, chn, chn_init_cfg) if chn_handle ==0: print("initCAN failed!" %(chn)) exit(0) ###SET filter ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_clear","0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d filter_clear failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_mode","0".encode("utf-8")) #标准帧滤波 if ret != ZCAN_STATUS_OK: print("Set CH%d filter_mode failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_start","0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d filter_start failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_end","0x7FF".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d filter_end failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_mode","1".encode("utf-8")) #扩展帧滤波 if ret != ZCAN_STATUS_OK: print("Set CH%d filter_mode failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_start","0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d filter_start failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_end","0x1FFFFFFF".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d filter_end failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/filter_ack","0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Set CH%d filter_ack failed!" %(chn)) exit(0) ret=zcanlib.StartCAN(chn_handle) if ret != ZCAN_STATUS_OK: print("startCAN failed!" %(chn)) exit(0) # ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/set_device_tx_echo","1".encode("utf-8")) #发送回显设置,0-禁用,1-开启 # if ret != ZCAN_STATUS_OK: # print("Set CH%d set_device_tx_echo failed!" %(chn)) # exit(0) ### Set Auto Transmit ''' #开启硬件定时发送代码 ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/clear_auto_send","0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Clear CH%d USBCANFD AutoSend failed!" %(chn)) exit(0) ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/auto_send",byref(AutoCAN_A)) #添加A can报文定时 ret = zcanlib.ZCAN_SetValue(device_handle, str(chn) + "/auto_send_canfd", byref(AutoCAN_B)) #添加B canfd报文定时 ret = zcanlib.ZCAN_SetValue(device_handle,str(chn)+"/apply_auto_send","0".encode("utf-8")) if ret != ZCAN_STATUS_OK: print("Apply CH%d USBCANFD AutoSend failed!" %(chn)) exit(0) ''' return chn_handle if __name__ == "__main__": zcanlib = ZCAN() testcantype =0 #0:CAN; 1:canfd handle = zcanlib.OpenDevice(ZCAN_USBCANFD_200U, 0,0) if handle == INVALID_DEVICE_HANDLE: print("Open CANFD Device failed!") exit(0) print("device handle:%d." %(handle)) info = zcanlib.GetDeviceInf(handle) print("Device Information:\n%s" %(info)) #set auto send obj AutoCAN_A = ZCAN_AUTO_TRANSMIT_OBJ() #CAN AutoCAN_B = ZCANFD_AUTO_TRANSMIT_OBJ() #canfd AutoCAN_A.enable = 1 #enable AutoCAN_A.index = 0 AutoCAN_A.interval = 200 #ms AutoCAN_A.obj.frame.can_id = 0x100 AutoCAN_A.obj.transmit_type = 0 AutoCAN_A.obj.frame.eff = 0 AutoCAN_A.obj.frame.rtr = 0 AutoCAN_A.obj.frame.can_dlc = 8 for j in range(AutoCAN_A.obj.frame.can_dlc): AutoCAN_A.obj.frame.data[j] = j AutoCAN_B.enable = 1 #enable AutoCAN_B.index = 1 AutoCAN_B.interval = 200 #ms AutoCAN_B.obj.frame.can_id = 0x300 AutoCAN_B.obj.transmit_type = 0 AutoCAN_B.obj.frame.eff = 0 AutoCAN_B.obj.frame.rtr = 0 AutoCAN_B.obj.frame.len = 8 for j in range(AutoCAN_B.obj.frame.len): AutoCAN_B.obj.frame.data[j] = j #Start CAN chn_handle = canfd_start(zcanlib, handle, 0) print("channel handle:%d." %(chn_handle)) #Send CAN Messages transmit_num = 10 msgs = (ZCAN_Transmit_Data * transmit_num)() for i in range(transmit_num): msgs[i].transmit_type = 0 #0-正常发送,2-自发自收 msgs[i].frame.eff = 0 #0-标准帧,1-扩展帧 msgs[i].frame.rtr = 0 #0-数据帧,1-远程帧 msgs[i].frame.can_id = i msgs[i].frame.can_dlc = 8 for j in range(msgs[i].frame.can_dlc): msgs[i].frame.data[j] = j ret = zcanlib.Transmit(chn_handle, msgs, transmit_num) print("Tranmit Num: %d." % ret) #Send CANFD Messages transmit_canfd_num = 10 canfd_msgs = (ZCAN_TransmitFD_Data * transmit_canfd_num)() for i in range(transmit_num): canfd_msgs[i].transmit_type = 0 #0-正常发送,2-自发自收 canfd_msgs[i].frame.eff = 0 #0-标准帧,1-扩展帧 canfd_msgs[i].frame.rtr = 0 #0-数据帧,1-远程帧 canfd_msgs[i].frame.brs = 1 #BRS 加速标志位:0不加速,1加速 canfd_msgs[i].frame.can_id = i canfd_msgs[i].frame.len = 8 for j in range(canfd_msgs[i].frame.len): canfd_msgs[i].frame.data[j] = j ret = zcanlib.TransmitFD(chn_handle, canfd_msgs, transmit_canfd_num) print("Tranmit CANFD Num: %d." % ret) thread=threading.Thread(target=input_thread) thread.start() #Receive Messages while True: rcv_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CAN) rcv_canfd_num = zcanlib.GetReceiveNum(chn_handle, ZCAN_TYPE_CANFD) if rcv_num: rcv_msg, rcv_num = zcanlib.Receive(chn_handle, rcv_num) for i in range(rcv_num): print("timestamps:%6fs,type:CAN, %s ,id:%s, dlc:%d, eff:%d, rtr:%d, data:%s" %( rcv_msg[i].timestamp/1000000,"tx" if (rcv_msg[i].frame.__pad&0x20) else "rx", hex(rcv_msg[i].frame.can_id), rcv_msg[i].frame.can_dlc, rcv_msg[i].frame.eff, rcv_msg[i].frame.rtr, ''.join(hex(rcv_msg[i].frame.data[j])+ ' 'for j in range(rcv_msg[i].frame.can_dlc)))) if rcv_canfd_num: rcv_canfd_msgs, rcv_canfd_num = zcanlib.ReceiveFD(chn_handle, rcv_canfd_num) for i in range(rcv_canfd_num): print("timestamp:%6fs,type:canfd, %s ,id:%s, len:%d, eff:%d, rtr:%d, esi:%d, brs: %d, data:%s" %( rcv_canfd_msgs[i].timestamp/1000000,"tx" if (rcv_canfd_msgs[i].frame.__pad&0x8) else "rx" , hex(rcv_canfd_msgs[i].frame.can_id), rcv_canfd_msgs[i].frame.len, rcv_canfd_msgs[i].frame.eff, rcv_canfd_msgs[i].frame.rtr, rcv_canfd_msgs[i].frame.esi, rcv_canfd_msgs[i].frame.brs, ''.join(hex(rcv_canfd_msgs[i].frame.data[j]) + ' ' for j in range(rcv_canfd_msgs[i].frame.len)))) if thread.is_alive() == False: break #Close CAN ret=zcanlib.ResetCAN(chn_handle) if ret==1: print("ResetCAN success! ") #Close Device ret=zcanlib.CloseDevice(handle) if ret==1: print("CloseDevice success! ") 这里面的main()函数是那些
06-13
#!/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() 帮我检查后生成一个完整能运行的代码
最新发布
12-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值