将目标设备更改通知发送到 "C:\WINDOWS\explorer.exe" 的窗口时超时

事件类型: 警告
事件来源: PlugPlayManager
事件种类: 无
事件 ID: 257
日期: 2014-7-23
事件: 20:04:53
用户: N/A
计算机: SKCHEMICAL
描述:
将目标设备更改通知发送到 "C:\WINDOWS\Explorer.EXE" 的窗口时超时


有关更多信息,请参阅在 http://go.microsoft.com/fwlink/events.asp 的帮助和支持中心。


解决方法:
http://support.microsoft.com/kb/924390/en-us  下载Hotfix Download Available 补丁。



#include "bloodpressuresetdialog.h" #include "resolutionadaptive.h" #include <QGridLayout> #include <QVBoxLayout> #include <QHBoxLayout> #include <QDebug> #include <QLoggingCategory> const QBluetoothUuid targetServiceUuid = QBluetoothUuid(QStringLiteral("0000fff0-0000-1000-8000-00805f9b34fb"));// 目标服务UUID const QBluetoothUuid targetCharUuid = QBluetoothUuid(QStringLiteral("0000fff4-0000-1000-8000-00805f9b34fb"));// 目标特征UUID BloodPressureSetDialog::BloodPressureSetDialog(QWidget *parent) : QDialog(parent), bleController(nullptr), currentService(nullptr) { //启用所有以 qt.bluetooth 为前缀的日志输出 QLoggingCategory::setFilterRules(QStringLiteral("qt.bluetooth* = true")); // 窗口设置 setWindowFlag(Qt::WindowContextHelpButtonHint, false); setMinimumSize(ResolutionAdaptive::size(600, 600)); setWindowTitle(tr("血压计配置")); // 主布局 auto *mainLayout = new QGridLayout(this); // 血压计型号选择分组 BloodPressureGroupBox = new QGroupBox(tr("血压计型号选择"), this); BloodPressureButtonGroup = new QButtonGroup(this); BloodPressure_YXBLE_Radio = new QRadioButton(tr("USB型"), this); BloodPressure_WXBLE_Radio = new QRadioButton(tr("无线蓝牙型"), this); BloodPressure_YXBLE_Radio->setChecked(true); BloodPressureButtonGroup->addButton(BloodPressure_YXBLE_Radio, 0); BloodPressureButtonGroup->addButton(BloodPressure_WXBLE_Radio, 1); auto *radioLayout = new QHBoxLayout(BloodPressureGroupBox); radioLayout->addWidget(BloodPressure_YXBLE_Radio); radioLayout->addWidget(BloodPressure_WXBLE_Radio); mainLayout->addWidget(BloodPressureGroupBox, 0, 0, 1, 2); // 栈式窗口 stack = new QStackedWidget(this); auto *YXBLEWidget = new QWidget(stack); // USB页面(空实现) WXBLEWidget = new QWidget(stack); // 蓝牙页面 stack->addWidget(YXBLEWidget); stack->addWidget(WXBLEWidget); mainLayout->addWidget(stack, 1, 0, 1, 2); // 保存按钮 SaveBtn = new QPushButton(tr("保存配置"), this); mainLayout->addWidget(SaveBtn, 2, 0, 1, 2, Qt::AlignCenter); // 初始化 initBluetoothWidget(); // 信号连接 connect(BloodPressureButtonGroup, QOverload<QAbstractButton *, bool>::of(&QButtonGroup::buttonToggled),this, &BloodPressureSetDialog::onRadioButtonToggled); connect(SaveBtn, &QPushButton::clicked, this, &BloodPressureSetDialog::onSaveClicked); } BloodPressureSetDialog::~BloodPressureSetDialog() { // 资源清理 if (currentService) { delete currentService; } if (bleController) { bleController->disconnectFromDevice(); delete bleController; } delete discoveryAgent; } //蓝牙界面初始 void BloodPressureSetDialog::initBluetoothWidget() { // 蓝牙页面布局 auto *mainLayout = new QVBoxLayout(WXBLEWidget); // 搜索按钮 searchButton = new QPushButton(tr("搜索蓝牙设备"), this); mainLayout->addWidget(searchButton); // 设备列表 deviceListWidget = new QListWidget(this); deviceListWidget->setStyleSheet("QListWidget::item { height: 50px; }"); mainLayout->addWidget(deviceListWidget); // 状态标签 statusLabel = new QLabel(tr("请点击搜索按钮查找设备"), this); mainLayout->addWidget(statusLabel); // 设备发现代理 discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this); discoveryAgent->setLowEnergyDiscoveryTimeout(5000); // 5秒超时 // 连接蓝牙信号 connect(searchButton, &QPushButton::clicked, this, &BloodPressureSetDialog::onSearchClicked); //当蓝牙搜索代理(discoveryAgent)在扫描过程中发现任何符合低功耗蓝牙(BLE)规范的设备触发 connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::deviceDiscovered,this, &BloodPressureSetDialog::onDeviceDiscovered); //当蓝牙搜索达到预设超时间完成搜索 connect(discoveryAgent, &QBluetoothDeviceDiscoveryAgent::finished,this, &BloodPressureSetDialog::onDiscoveryFinished); //当搜索过程中出现异常(如蓝牙硬件未启用、信号干扰导致通信失败等)触发 connect(discoveryAgent, QOverload<QBluetoothDeviceDiscoveryAgent::Error>::of(&QBluetoothDeviceDiscoveryAgent::error),this, &BloodPressureSetDialog::onDiscoveryError); } //选项界面切换 void BloodPressureSetDialog::onRadioButtonToggled(QAbstractButton *button, bool checked) { if (checked) { if (button == BloodPressure_YXBLE_Radio) { stack->setCurrentIndex(0); // 显示USB页面 } else if (button == BloodPressure_WXBLE_Radio) { stack->setCurrentIndex(1); // 显示蓝牙页面 } } } //开始搜索按钮点击 void BloodPressureSetDialog::onSearchClicked() { //清空设备列表 deviceListWidget->clear(); statusLabel->setText(tr("正在搜索蓝牙设备...")); //搜索按钮失能 searchButton->setEnabled(false); qDebug()<<"正在搜索蓝牙设备..."; // 开始搜索低功耗蓝牙设备 discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod); } //当蓝牙搜索代理(discoveryAgent)在扫描过程中发现任何符合低功耗蓝牙(BLE)规范的设备触发 void BloodPressureSetDialog::onDeviceDiscovered(const QBluetoothDeviceInfo &device) { // 只处理BLE设备 if (!(device.coreConfigurations() & QBluetoothDeviceInfo::LowEnergyCoreConfiguration)) { return; } QString deviceName = device.name(); if (deviceName.isEmpty()) { deviceName = tr("未知设备"); } // 创建列表项 auto *item = new QListWidgetItem(deviceListWidget); auto *itemWidget = new QWidget(deviceListWidget); auto *itemLayout = new QHBoxLayout(itemWidget); itemLayout->setContentsMargins(5, 5, 5, 5); // 设备信息标签 auto *deviceLabel = new QLabel(deviceName, itemWidget); // 连接按钮 auto *connectBtn = new QPushButton(tr("连接"), itemWidget); connectBtn->setMinimumWidth(80); connect(connectBtn, &QPushButton::clicked,this, [this, device](){ onConnectDevice(device); }); itemLayout->addWidget(deviceLabel); itemLayout->addStretch(); itemLayout->addWidget(connectBtn); deviceListWidget->setItemWidget(item, itemWidget); } //蓝牙搜索完成 void BloodPressureSetDialog::onDiscoveryFinished() { statusLabel->setText(tr("搜索完成,找到 %1 个设备").arg(deviceListWidget->count())); searchButton->setEnabled(true); qDebug()<<tr("搜索完成,找到 %1 个设备").arg(deviceListWidget->count()); } //搜索过程出现异常 void BloodPressureSetDialog::onDiscoveryError(QBluetoothDeviceDiscoveryAgent::Error error) { QString errorText; switch (error) { case QBluetoothDeviceDiscoveryAgent::PoweredOffError: errorText = tr("蓝牙未开启,请先开启蓝牙"); break; case QBluetoothDeviceDiscoveryAgent::InputOutputError: errorText = tr("蓝牙通信错误"); break; default: errorText = tr("搜索错误: %1").arg(discoveryAgent->errorString()); } statusLabel->setText(errorText); searchButton->setEnabled(true); } //保存配置 void BloodPressureSetDialog::onSaveClicked() { if (BloodPressure_WXBLE_Radio->isChecked() && !currentConnectedDevice.address().isNull()) { QString info = QString("已保存蓝牙配置: %1 (%2)") .arg(currentConnectedDevice.name()) .arg(currentConnectedDevice.address().toString()); statusLabel->setText(info); qDebug() << info; } else if (BloodPressure_YXBLE_Radio->isChecked()) { statusLabel->setText(tr("已保存USB配置")); qDebug() << "保存USB配置"; } } //连接按钮按下 void BloodPressureSetDialog::onConnectDevice(const QBluetoothDeviceInfo &device) { statusLabel->setText(tr("正在连接 %1...").arg(device.name())); // 如果已有连接,先断开 if (bleController) { qDebug()<<"已有连接,bleController执行断开"; bleController->disconnectFromDevice(); delete bleController; bleController = nullptr; } if (currentService) { qDebug()<<"已有服务,currentService执行断开"; delete currentService; currentService = nullptr; } // 保存当前连接的设备信息 currentConnectedDevice = device; // 创建BLE控制器 bleController = QLowEnergyController::createCentral(device, this); if (!bleController) { statusLabel->setText(tr("创建控制器失败")); return; } qDebug()<<QString("创建%1控制器成功").arg(currentConnectedDevice.name()); //当 BLE 控制器成功与蓝牙设备建立连接触发 connect(bleController, &QLowEnergyController::connected,this, &BloodPressureSetDialog::onControllerConnected); //当 BLE 控制器与蓝牙设备的连接断开触发 connect(bleController, &QLowEnergyController::disconnected,this, &BloodPressureSetDialog::onControllerDisconnected); //当 BLE 控制器在连接或通信过程中发生错误触发 connect(bleController, QOverload<QLowEnergyController::Error>::of(&QLowEnergyController::error),this, &BloodPressureSetDialog::onControllerError); //当 BLE 控制器成功发现蓝牙设备提供的一个服务触发 connect(bleController, &QLowEnergyController::serviceDiscovered,this, &BloodPressureSetDialog::onServiceDiscovered); //当 BLE 控制器完成对蓝牙设备所有服务的搜索后触发 connect(bleController, &QLowEnergyController::discoveryFinished,this, &BloodPressureSetDialog::onServiceDiscoveryFinished); // 开始连接 bleController->connectToDevice(); } //当 BLE 控制器成功与蓝牙设备建立连接触发 void BloodPressureSetDialog::onControllerConnected() { statusLabel->setText(tr("连接成功,正在搜索服务...")); //qDebug()<<"bleController当前状态:"<<bleController->state(); QTimer::singleShot(300, this, [this]() { bleController->discoverServices(); }); } //当 BLE 控制器与蓝牙设备的连接断开触发 void BloodPressureSetDialog::onControllerDisconnected() { qDebug() << "设备已断开连接,服务可能失效"; statusLabel->setText(tr("设备已断开连接")); currentConnectedDevice = QBluetoothDeviceInfo(); if (currentService) { delete currentService; currentService = nullptr; } } //当 BLE 控制器在连接或通信过程中发生错误 void BloodPressureSetDialog::onControllerError(QLowEnergyController::Error error) { statusLabel->setText(tr("连接错误: %1").arg(bleController->errorString())); } //当 BLE 控制器成功发现蓝牙设备提供的一个服务触发 void BloodPressureSetDialog::onServiceDiscovered(const QBluetoothUuid &newServiceUUid) { //qDebug()<<"当前的服务UUid:"<<newServiceUUid; m_ServiceUuidList.append(newServiceUUid); } //当 BLE 控制器完成对蓝牙设备所有服务的搜索后触发 void BloodPressureSetDialog::onServiceDiscoveryFinished() { // 先创建一个字符串来存储所有服务UUID QString allServices; for (const auto &uuid : m_ServiceUuidList) { allServices += uuid.toString() + "\n"; } qDebug() << QString("BLE控制器完成对蓝牙设备所有服务的搜索,共发现 %1 个服务:").arg(m_ServiceUuidList.count()); qDebug().noquote() << allServices; bool hasTargetService = m_ServiceUuidList.contains(targetServiceUuid); if (hasTargetService) { statusLabel->setText(tr("发现目标服务,设备可用")); qDebug() << "找到目标服务 UUID: " << targetServiceUuid.toString(); //开始连接目标服务 currentService = bleController->createServiceObject(targetServiceUuid); if(currentService) { //当服务状态发生变化触发 connect(currentService, &QLowEnergyService::stateChanged,this, &BloodPressureSetDialog::onServiceStateChanged); //当服务操作错误 connect(currentService, QOverload<QLowEnergyService::ServiceError>::of(&QLowEnergyService::error),this, &BloodPressureSetDialog::onServiceError); // 连接特征读取完成信号 connect(currentService, &QLowEnergyService::characteristicRead,this,&BloodPressureSetDialog::onCharacteristicRead); qDebug() << "开始发现服务详情:currentService->discoverDetails()"; currentService->discoverDetails(); } } else { statusLabel->setText(tr("未发现目标服务,设备可能不兼容")); qDebug() << "未找到目标服务 UUID: " << targetServiceUuid.toString(); } // 清空服务列表,避免下次搜索干扰 m_ServiceUuidList.clear(); } //当前服务状态变化 void BloodPressureSetDialog::onServiceStateChanged(QLowEnergyService::ServiceState newState) { if(currentService) { switch(newState) { case QLowEnergyService::InvalidService://表示服务处于无效状态。通常在服务未正确初始化、连接失败,或已被销毁出现,此无法对服务进行任何有效操作(如发现特征、读写数据等)。 { qDebug()<<"InvalidService状态"; statusLabel->setText(tr("服务处于无效状态")); } break; case QLowEnergyService::DiscoveryRequired://表示服务已被识别(已知其起始和结束句柄),但尚未进行详细信息的发现。此需要调用 discoverDetails() 方法触发服务详情(如特征、描述符等)的发现过程,否则无法访问服务的具体功能。 { qDebug()<<"DiscoveryRequired状态"; } break; case QLowEnergyService::DiscoveringServices://表示服务正在进行详情发现(discoverDetails() 已被调用且正在执行)。在此状态下,系统正在与 BLE 设备通信,获取服务包含的特征、特征属性、描述符等信息,此应避免对服务进行其他操作,等待发现完成。 { qDebug()<<"DiscoveringServices状态"; } break; case QLowEnergyService::ServiceDiscovered://表示服务的详情已完全发现并同步完成。此可以正常访问服务的特征(如读取、写入特征值,设置通知等),是服务可用的主要状态。 { qDebug()<<"ServiceDiscovered状态"; const QLowEnergyCharacteristic targetChar = currentService->characteristic(targetCharUuid); // 打印特征属性(调试用) qDebug() << "特征属性:" << targetChar.properties(); if (targetChar.properties() & QLowEnergyCharacteristic::Read) { qDebug()<<"执行currentService->readCharacteristic(targetChar);"; currentService->readCharacteristic(targetChar); }else{ qDebug()<<"特征值不支持读取操作"; } statusLabel->setText(tr("服务就绪,正在准备数据交互...")); // 查找目标特征(targetCharUuid) const QList<QLowEnergyCharacteristic> chars = currentService->characteristics(); bool foundTargetChar = false; for (const auto &ch : chars) { if (ch.uuid() == targetCharUuid) { foundTargetChar = true; qDebug()<<"查找目标特征targetCharUuid:"<<ch.uuid(); break; } } if (!foundTargetChar) { qDebug() << "未找到目标特征 UUID: " << targetCharUuid.toString(); statusLabel->setText(tr("未找到目标特征,无法通信")); // 若未找到特征,主动断开连接(避免设备超时) if (bleController) { bleController->disconnectFromDevice(); } } } break; case QLowEnergyService::LocalService://表示该服务是本地设备(当前应用所在设备)创建的本地服务,而非远程 BLE 设备提供的服务。本地服务通常用于将当前设备作为 BLE 服务器,向其他设备提供数据或功能。 { qDebug()<<"LocalService状态"; } break; default: qDebug()<<"未知状态"; break; } } } //服务操作错误 void BloodPressureSetDialog::onServiceError(QLowEnergyService::ServiceError error) { //qDebug() << "服务错误导致状态失效:" << error; switch(error) { case QLowEnergyService::NoError://无错误 break; case QLowEnergyService::OperationError://通用操作错误 qDebug()<<"OperationError"; break; case QLowEnergyService::CharacteristicWriteError://特征值写入错误 qDebug()<<"CharacteristicWriteError"; break; case QLowEnergyService::DescriptorWriteError://描述符写入错误 qDebug()<<"DescriptorWriteError"; break; case QLowEnergyService::UnknownError://未知错误 qDebug()<<"UnknownError"; break; case QLowEnergyService::CharacteristicReadError://特征值读取错误 qDebug()<<"CharacteristicReadError"; break; case QLowEnergyService::DescriptorReadError://描述符读取错误 qDebug()<<"DescriptorReadError"; break; break; } } //特征读取 void BloodPressureSetDialog::onCharacteristicRead(const QLowEnergyCharacteristic &info, const QByteArray &value) { QString ch = info.uuid().toString() + " - Characteristic read:" + QString(value); qDebug()<<ch; statusLabel->setText(ch); } 正在搜索蓝牙设备... qt.bluetooth.winrt: Worker started qt.bluetooth.winrt: BTLE scan completed qt.bluetooth.winrt: onBluetoothLEDeviceFound: No device given qt.bluetooth.winrt: Discovered BTLE device: "263711541014828" "Q_BASH_EFD820B9B12C" Num UUIDs 2 RSSI: -70 Num manufacturer data 1 qt.bluetooth.winrt: Discovered BTLE device: "263711541014828" "Q_BASH_EFD820B9B12C" Num UUIDs 2 RSSI: -70 Num manufacturer data 1 qt.bluetooth.winrt: Updating device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Discovered BTLE device: "248235452300580" "AL_WBP" Num UUIDs 1 RSSI: -38 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Discovered BTLE device: "139883855153833" "Lck1_7F393F7F0AA9" Num UUIDs 1 RSSI: -46 Num manufacturer data 0 qt.bluetooth.winrt: Discovered BTLE device: "181149789377595" "LKM1S1-D8D43B" Num UUIDs 0 RSSI: -56 Num manufacturer data 0 qt.bluetooth.winrt: Discovered BTLE device: "119263911754715" "Bluetooth 6c:78:4b:18:3b:db" Num UUIDs 0 RSSI: -70 Num manufacturer data 0 qt.bluetooth.winrt: Discovered BTLE device: "85447561129030" "Bluetooth 4d:b6:cf:87:2c:46" Num UUIDs 0 RSSI: -80 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: onBluetoothLEDeviceFound: No device given qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Discovered BTLE device: "229505267960818" "hellobike" Num UUIDs 0 RSSI: -74 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: onBluetoothLEDeviceFound: No device given qt.bluetooth.winrt: onBluetoothLEDeviceFound: No device given qt.bluetooth.winrt: Discovered BTLE device: "135612681587525" "Bluetooth 7b:56:c9:b6:8b:45" Num UUIDs 0 RSSI: -72 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Discovered BTLE device: "12916180417167" "Lck1_0BBF48587A8F" Num UUIDs 1 RSSI: -46 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: onBluetoothLEDeviceFound: No device given qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Discovered BTLE device: "93424836092648" "Bluetooth 54:f8:2a:2b:22:e8" Num UUIDs 1 RSSI: -78 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: onBluetoothLEDeviceFound: No device given qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" qt.bluetooth.winrt: Updating data for device "Lck1_7F393F7F0AA9" "7F:39:3F:7F:0A:A9" qt.bluetooth.winrt: Discovered BTLE device: "89231211862959" "Bluetooth 51:27:c2:af:9b:af" Num UUIDs 0 RSSI: -62 Num manufacturer data 0 qt.bluetooth.winrt: Updating data for device "Q_BASH_EFD820B9B12C" "EF:D8:20:B9:B1:2C" qt.bluetooth.winrt: Updating data for device "AL_WBP" "E1:C4:D1:F4:7D:24" "搜索完成,找到 11 个设备" qt.bluetooth.winrt: Using new low energy controller "创建AL_WBP控制器成功" qt.bluetooth.winrt: QLowEnergyControllerPrivateWinRTNew::connectToDevice qt.bluetooth.winrt: QLowEnergyControllerPrivateWinRTNew::registerForStatusChanges qt.bluetooth.winrt: Service discovery initiated qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::onServiceDiscoveryFinished Changing service pointer from thread QThread(0x1fa05908540) "BLE控制器完成对蓝牙设备所有服务的搜索,共发现 7 个服务:" {00001800-0000-1000-8000-00805f9b34fb} {00001801-0000-1000-8000-00805f9b34fb} {00001810-0000-1000-8000-00805f9b34fb} {0000fff0-0000-1000-8000-00805f9b34fb} {8e400001-f315-4f60-9fb8-838830daea50} {00001805-0000-1000-8000-00805f9b34fb} {0000180a-0000-1000-8000-00805f9b34fb} 找到目标服务 UUID: "{0000fff0-0000-1000-8000-00805f9b34fb}" 开始发现服务详情:currentService->discoverDetails() DiscoveringServices状态 qt.bluetooth.winrt: QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails "{0000fff0-0000-1000-8000-00805f9b34fb}" qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::discoverServiceDetails Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt: QWinRTLowEnergyServiceHandlerNew::QWinRTLowEnergyServiceHandlerNew qt.bluetooth.winrt: QWinRTLowEnergyServiceHandlerNew::obtainCharList qt.bluetooth.winrt: Registering characteristic "{0000fff4-0000-1000-8000-00805f9b34fb}" in service "{0000fff0-0000-1000-8000-00805f9b34fb}" for value changes qt.bluetooth.winrt: Could not obtain native service for Uuid "{0000fff0-0000-1000-8000-00805f9b34fb}" qt.bluetooth.winrt: Could not obtain native characteristic "{0000fff4-0000-1000-8000-00805f9b34fb}" from service "{0000fff0-0000-1000-8000-00805f9b34fb}". Qt will not be able to signal changes for this characteristic. ServiceDiscovered状态 特征属性: QFlags(0x2|0x8|0x10) 执行currentService->readCharacteristic(targetChar); qt.bluetooth.winrt: QLowEnergyControllerPrivateWinRTNew::readCharacteristic QSharedPointer(QLowEnergyServicePrivate(0x1fa0b3046f0)) 16 qt.bluetooth.winrt.service.thread: QLowEnergyControllerPrivateWinRTNew::readCharacteristic Changing service pointer from thread QThread(0x1fa05908540) qt.bluetooth.winrt: Could not obtain native service for Uuid "{0000fff0-0000-1000-8000-00805f9b34fb}" qt.bluetooth.winrt: Could not obtain native characteristic "{0000fff4-0000-1000-8000-00805f9b34fb}" from service "{0000fff0-0000-1000-8000-00805f9b34fb}" CharacteristicReadError 查找目标特征targetCharUuid: "{0000fff4-0000-1000-8000-00805f9b34fb}" InvalidService状态 qt.bluetooth.winrt: Unregistering 0 value change tokens qt.bluetooth.winrt: QLowEnergyControllerPrivateWinRTNew::unregisterFromStatusChanges 设备已断开连接,服务可能失效 qt.bluetooth.winrt: QLowEnergyControllerPrivateWinRTNew::unregisterFromStatusChanges qt.bluetooth.winrt: Unregistering 0 value change tokens
07-23
#!/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() 运行生成的__MEI1377082以及jb.station还是清理不干净
最新发布
12-05
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值