fix: 修复Windows退出托盘图标残留问题 (#3797)

This commit is contained in:
阿珏
2026-06-06 22:27:39 +08:00
committed by GitHub
parent 1392ef6238
commit ab6266f745
+25
View File
@@ -1460,6 +1460,11 @@ pub fn run() {
tauri::async_runtime::spawn(async move {
save_window_state_before_exit(&app_handle);
cleanup_before_exit(&app_handle).await;
// 先于 std::process::exit 显式移除托盘图标。
// 进程直接退出时 Tauri 运行时不走正常 Drop 流程,
// 不会向 Windows Shell 发送 NIM_DELETE,导致已退出的进程
// 注册的图标仍残留在系统托盘(鼠标悬停 Shell 才会重绘发现进程已死)。
remove_tray_icon_before_exit(&app_handle);
log::info!("清理完成,退出应用");
// 短暂等待确保所有 I/O 操作(如数据库写入)刷新到磁盘
@@ -1607,6 +1612,26 @@ pub async fn cleanup_before_exit(app_handle: &tauri::AppHandle) {
}
}
/// 主动从系统托盘移除托盘图标。
///
/// `std::process::exit` 会绕过 Tauri 运行时,触发不了 `TrayIcon::drop()`
/// 也就不会向 Windows Shell 发 `NIM_DELETE`。结果是进程退出后托盘里
/// 仍保留一个死图标的缓存占位(Shell 不会主动重绘,需要鼠标悬停才刷新)。
///
/// 通过 `set_visible(false)` 走 `WM_USER_HIDE_TRAYICON` 消息路径,
/// 触发 tray-icon 内部的 `remove_tray_icon` → `Shell_NotifyIconW(NIM_DELETE)`
/// 在进程结束前干净地把图标摘掉。其它平台 `set_visible(false)` 也是
/// 正常的隐藏/移除语义,作为跨平台兜底也安全。
fn remove_tray_icon_before_exit(app_handle: &tauri::AppHandle) {
if let Some(tray) = app_handle.tray_by_id(tray::TRAY_ID) {
if let Err(e) = tray.set_visible(false) {
log::warn!("退出时移除托盘图标失败: {e}");
} else {
log::info!("已显式从系统托盘移除图标");
}
}
}
// ============================================================
// 启动时恢复代理状态
// ============================================================