feat:增加Windows桌面图标缓存清理功能
This commit is contained in:
1 parent
75bf59adeb
commit
aada05a1fc
3 files changed
+117
-36
No files matched your search
+80
-35
@@ -7,6 +7,12 @@ use std::path::{Path, PathBuf};
|
||||
use std::fs;
|
||||
use encoding_rs::GBK;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use std::os::windows::process::CommandExt;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct UpxOptions {
|
||||
mode: String,
|
||||
@@ -15,6 +21,7 @@ struct UpxOptions {
|
||||
compression_level: String,
|
||||
backup: bool,
|
||||
ultra_brute: bool,
|
||||
force: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
@@ -24,53 +31,42 @@ struct ScanFolderOptions {
|
||||
}
|
||||
|
||||
// 获取UPX可执行文件路径
|
||||
fn get_upx_path() -> PathBuf {
|
||||
// 尝试1: 使用打包后的upx (在exe同目录下)
|
||||
fn get_upx_path() -> Option<PathBuf> {
|
||||
// 打包后的位置
|
||||
if let Ok(exe_path) = std::env::current_exe() {
|
||||
if let Some(exe_dir) = exe_path.parent() {
|
||||
let bundled_upx = exe_dir.join("upx.exe");
|
||||
if bundled_upx.exists() {
|
||||
return bundled_upx;
|
||||
let upx = exe_dir.join("_up_/upx/upx.exe");
|
||||
if upx.exists() {
|
||||
return Some(upx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 尝试2: 使用开发环境的upx (src-tauri/../upx/upx.exe)
|
||||
let dev_upx = PathBuf::from("../../upx/upx.exe");
|
||||
// 开发环境
|
||||
let dev_upx = PathBuf::from("../upx/upx.exe");
|
||||
if dev_upx.exists() {
|
||||
return dev_upx;
|
||||
return Some(dev_upx);
|
||||
}
|
||||
|
||||
// 尝试3: 另一个开发环境路径
|
||||
let dev_upx2 = PathBuf::from("../upx/upx.exe");
|
||||
if dev_upx2.exists() {
|
||||
return dev_upx2;
|
||||
}
|
||||
|
||||
// 尝试4: 使用系统PATH中的upx (降级方案)
|
||||
PathBuf::from("upx")
|
||||
None
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn process_upx(options: UpxOptions) -> Result<String, String> {
|
||||
// 获取UPX可执行文件路径
|
||||
let upx_path = get_upx_path();
|
||||
let upx_path = get_upx_path().ok_or("未找到 UPX 工具!请确保安装完整")?;
|
||||
|
||||
// 检查 UPX 是否可用
|
||||
let mut upx_check = Command::new(&upx_path);
|
||||
|
||||
// 在 Windows 上隐藏控制台窗口
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use std::os::windows::process::CommandExt;
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
upx_check.creation_flags(CREATE_NO_WINDOW);
|
||||
}
|
||||
upx_check.creation_flags(CREATE_NO_WINDOW);
|
||||
|
||||
let upx_check = upx_check.arg("--version").output();
|
||||
|
||||
if upx_check.is_err() {
|
||||
return Err("未找到 UPX 工具!".to_string());
|
||||
return Err("UPX 工具无法执行!".to_string());
|
||||
}
|
||||
|
||||
// 检查输入文件是否存在
|
||||
@@ -101,11 +97,7 @@ async fn process_upx(options: UpxOptions) -> Result<String, String> {
|
||||
|
||||
// 在 Windows 上隐藏控制台窗口
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use std::os::windows::process::CommandExt;
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
}
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
|
||||
// 判断是否覆盖原文件
|
||||
let is_overwrite = options.input_file == options.output_file;
|
||||
@@ -122,6 +114,11 @@ async fn process_upx(options: UpxOptions) -> Result<String, String> {
|
||||
cmd.arg(format!("-{}", options.compression_level));
|
||||
}
|
||||
|
||||
// 添加强制压缩参数
|
||||
if options.force {
|
||||
cmd.arg("--force");
|
||||
}
|
||||
|
||||
if is_overwrite {
|
||||
// 直接覆盖原文件,不使用 -o 参数
|
||||
cmd.arg(&options.input_file);
|
||||
@@ -137,6 +134,11 @@ async fn process_upx(options: UpxOptions) -> Result<String, String> {
|
||||
// 脱壳模式
|
||||
cmd.arg("-d");
|
||||
|
||||
// 添加强制压缩参数(脱壳时也可能需要)
|
||||
if options.force {
|
||||
cmd.arg("--force");
|
||||
}
|
||||
|
||||
if is_overwrite {
|
||||
// 直接覆盖原文件
|
||||
cmd.arg(&options.input_file);
|
||||
@@ -267,17 +269,13 @@ fn scan_folder(options: ScanFolderOptions) -> Result<Vec<String>, String> {
|
||||
// 获取UPX版本
|
||||
#[tauri::command]
|
||||
fn get_upx_version() -> Result<String, String> {
|
||||
let upx_path = get_upx_path();
|
||||
let upx_path = get_upx_path().ok_or("未找到 UPX 工具!")?;
|
||||
|
||||
let mut cmd = Command::new(&upx_path);
|
||||
|
||||
// 在 Windows 上隐藏控制台窗口
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use std::os::windows::process::CommandExt;
|
||||
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
}
|
||||
cmd.creation_flags(CREATE_NO_WINDOW);
|
||||
|
||||
match cmd.arg("--version").output() {
|
||||
Ok(output) => {
|
||||
@@ -293,11 +291,58 @@ fn get_upx_version() -> Result<String, String> {
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新图标缓存
|
||||
#[tauri::command]
|
||||
#[allow(dead_code)]
|
||||
async fn refresh_icon_cache() -> Result<(), String> {
|
||||
// 后台执行刷新
|
||||
tokio::task::spawn_blocking(move || {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
// 1. 关闭 Explorer
|
||||
let _ = Command::new("taskkill")
|
||||
.args(&["/f", "/im", "explorer.exe"])
|
||||
.creation_flags(CREATE_NO_WINDOW)
|
||||
.output();
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
// 2. 删除图标缓存
|
||||
if let Ok(userprofile) = std::env::var("USERPROFILE") {
|
||||
let cache_db = format!("{}\\AppData\\Local\\IconCache.db", userprofile);
|
||||
let _ = fs::remove_file(&cache_db);
|
||||
|
||||
// 删除缩略图缓存
|
||||
let explorer_path = format!("{}\\AppData\\Local\\Microsoft\\Windows\\Explorer", userprofile);
|
||||
if let Ok(entries) = fs::read_dir(&explorer_path) {
|
||||
for entry in entries.flatten() {
|
||||
let path = entry.path();
|
||||
if let Some(name) = path.file_name().and_then(|n| n.to_str()) {
|
||||
if name.starts_with("thumbcache_") {
|
||||
let _ = fs::remove_file(&path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::thread::sleep(std::time::Duration::from_millis(500));
|
||||
|
||||
// 3. 重启 Explorer
|
||||
let _ = Command::new("explorer.exe")
|
||||
.creation_flags(CREATE_NO_WINDOW)
|
||||
.spawn();
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.invoke_handler(tauri::generate_handler![process_upx, scan_folder, get_upx_version])
|
||||
.invoke_handler(tauri::generate_handler![process_upx, scan_folder, get_upx_version, refresh_icon_cache])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
@@ -16,6 +16,11 @@
|
||||
<span id="upx-version" class="text-gray-400 text-xs select-none"></span>
|
||||
</div>
|
||||
<div class="flex items-center space-x-1">
|
||||
<button id="refresh-icon-btn" class="w-9 h-9 hover:bg-gray-100 flex items-center justify-center transition-all duration-200" style="border-radius: 0.3rem;" title="刷新图标缓存">
|
||||
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
|
||||
</svg>
|
||||
</button>
|
||||
<button id="settings-btn" class="w-9 h-9 hover:bg-gray-100 flex items-center justify-center transition-all duration-200" style="border-radius: 0.3rem;" title="设置">
|
||||
<svg class="w-4 h-4 text-gray-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
|
||||
@@ -138,6 +143,14 @@
|
||||
<p class="text-xs text-gray-500 mt-0.5">处理文件夹时,递归处理所有子目录</p>
|
||||
</div>
|
||||
</label>
|
||||
|
||||
<label class="flex items-start space-x-3 cursor-pointer p-2.5 hover:bg-gray-50 transition-colors" style="border-radius: 0.3rem;">
|
||||
<input type="checkbox" id="force-compress" class="w-4 h-4 mt-0.5 text-blue-600 border-gray-300 rounded focus:ring-2 focus:ring-blue-500 cursor-pointer">
|
||||
<div class="flex-1">
|
||||
<span class="text-sm font-medium text-gray-800">强制压缩</span>
|
||||
<p class="text-xs text-gray-500 mt-0.5">强制处理受保护的文件(如 GUARD_CF),可能移除安全特性</p>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
+24
-1
@@ -13,10 +13,12 @@ const overwriteCheckbox = document.getElementById('overwrite');
|
||||
const backupCheckbox = document.getElementById('backup');
|
||||
const ultraBruteCheckbox = document.getElementById('ultra-brute');
|
||||
const includeSubfoldersCheckbox = document.getElementById('include-subfolders');
|
||||
const forceCompressCheckbox = document.getElementById('force-compress');
|
||||
const logOutput = document.getElementById('log-output');
|
||||
const settingsModal = document.getElementById('settings-modal');
|
||||
const settingsBtn = document.getElementById('settings-btn');
|
||||
const closeSettingsBtn = document.getElementById('close-settings');
|
||||
const refreshIconBtn = document.getElementById('refresh-icon-btn');
|
||||
|
||||
// 窗口控制按钮
|
||||
const minimizeBtn = document.getElementById('titlebar-minimize');
|
||||
@@ -84,6 +86,11 @@ function initWindowControls() {
|
||||
|
||||
// 操作按钮初始化
|
||||
function initOperationButtons() {
|
||||
// 刷新图标缓存按钮
|
||||
refreshIconBtn.addEventListener('click', async () => {
|
||||
await handleRefreshIcon();
|
||||
});
|
||||
|
||||
// 设置按钮 - 显示全局设置
|
||||
settingsBtn.addEventListener('click', () => {
|
||||
showSettingsModal();
|
||||
@@ -496,12 +503,17 @@ async function processUpx(mode, inputFile, outputFile) {
|
||||
output_file: outputFile,
|
||||
compression_level: getCompressionLevel(),
|
||||
backup: backupCheckbox.checked,
|
||||
ultra_brute: ultraBruteCheckbox.checked
|
||||
ultra_brute: ultraBruteCheckbox.checked,
|
||||
force: forceCompressCheckbox.checked
|
||||
};
|
||||
|
||||
if (ultraBruteCheckbox.checked) {
|
||||
addLog('已启用极限压缩模式', 'info');
|
||||
}
|
||||
|
||||
if (forceCompressCheckbox.checked) {
|
||||
addLog('已启用强制压缩模式', 'warning');
|
||||
}
|
||||
|
||||
addLog(`开始${mode === 'compress' ? '加壳压缩' : '脱壳解压'}...`, 'info');
|
||||
|
||||
@@ -515,6 +527,17 @@ async function processUpx(mode, inputFile, outputFile) {
|
||||
}
|
||||
}
|
||||
|
||||
// 刷新图标缓存
|
||||
async function handleRefreshIcon() {
|
||||
try {
|
||||
addLog('正在刷新图标缓存...', 'info');
|
||||
await invoke('refresh_icon_cache');
|
||||
addLog('图标缓存刷新完成', 'success');
|
||||
} catch (error) {
|
||||
addLog(`刷新失败: ${error}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// 添加日志
|
||||
function addLog(message, type = 'info', highlight = false) {
|
||||
const logLine = document.createElement('div');
|
||||
|
||||
Reference in new issue
Block a user