fix: backup_registry 改为内部读取注册表当前值,不再依赖前端传入数据

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-26 22:04:16 +08:00
parent 2775a3a588
commit 804e02004d
3 changed files with 30 additions and 17 deletions
+24 -11
View File
@@ -1,5 +1,4 @@
use chrono::Local;
use std::fs;
use std::path::PathBuf;
fn backup_base_dir() -> PathBuf {
@@ -17,27 +16,41 @@ pub fn get_appdata_dir() -> String {
}
/// 备份当前注册表中的系统 PATH 和用户 PATH
/// 返回备份文件的路径
/// 在保存前调用,备份的是注册表中的当前值(保存前的状态)
#[tauri::command]
pub fn backup_registry(custom_dir: Option<String>, sys_paths: Vec<String>, user_paths: Vec<String>) -> Result<String, String> {
// 确定备份目录
pub fn backup_registry(custom_dir: Option<String>) -> Result<String, String> {
use crate::commands::registry;
use winreg::enums::*;
let backup_dir = match custom_dir {
Some(ref dir) if !dir.is_empty() => PathBuf::from(dir),
Some(ref dir) if !dir.is_empty() => std::path::PathBuf::from(dir),
_ => backup_base_dir(),
};
// 创建目录
fs::create_dir_all(&backup_dir)
std::fs::create_dir_all(&backup_dir)
.map_err(|e| format!("无法创建备份目录: {}", e))?;
// 生成带时间戳的文件名
// 读取当前注册表中的值(保存前的旧值)
let sys_paths = registry::load_paths(
HKEY_LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment",
"系统",
)?;
let user_paths = registry::load_paths(
HKEY_CURRENT_USER,
"Environment",
"用户",
)?;
let timestamp = Local::now().format("%Y%m%d_%H%M%S_%3f");
let filename = format!("path_backup_{}.txt", timestamp);
let filepath = backup_dir.join(&filename);
// 写入备份内容
let mut content = String::new();
content.push_str(&format!("PathEditor Backup - {}\n", Local::now().format("%Y-%m-%d %H:%M:%S")));
content.push_str(&format!(
"PathEditor Backup - {}\n",
Local::now().format("%Y-%m-%d %H:%M:%S")
));
content.push_str("\n[System PATH]\n");
for path in &sys_paths {
content.push_str(&format!("{}\n", path));
@@ -47,7 +60,7 @@ pub fn backup_registry(custom_dir: Option<String>, sys_paths: Vec<String>, user_
content.push_str(&format!("{}\n", path));
}
fs::write(&filepath, &content)
std::fs::write(&filepath, &content)
.map_err(|e| format!("无法写入备份文件: {}", e))?;
let result = filepath.to_string_lossy().to_string();
+4 -4
View File
@@ -5,7 +5,7 @@ const SYS_REG_PATH: &str = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\
const USER_REG_PATH: &str = "Environment";
const PATH_VALUE: &str = "Path";
fn load_paths(root: winreg::HKEY, sub_path: &str, label: &str) -> Result<Vec<String>, String> {
pub(crate) fn load_paths(root: winreg::HKEY, sub_path: &str, label: &str) -> Result<Vec<String>, String> {
let key = RegKey::predef(root);
let env_key = key
.open_subkey_with_flags(sub_path, KEY_READ)
@@ -18,7 +18,7 @@ fn load_paths(root: winreg::HKEY, sub_path: &str, label: &str) -> Result<Vec<Str
Ok(split_path(&value))
}
fn save_paths(root: winreg::HKEY, sub_path: &str, label: &str, paths: &[String]) -> Result<(), String> {
pub(crate) fn save_paths(root: winreg::HKEY, sub_path: &str, label: &str, paths: &[String]) -> Result<(), String> {
let value = join_path(paths);
// Windows 注册表 REG_EXPAND_SZ 上限 32767 字符
@@ -63,14 +63,14 @@ pub fn save_user_paths(paths: Vec<String>) -> Result<(), String> {
save_paths(HKEY_CURRENT_USER, USER_REG_PATH, "用户", &paths)
}
fn split_path(raw: &str) -> Vec<String> {
pub(crate) fn split_path(raw: &str) -> Vec<String> {
raw.split(';')
.map(|s| s.trim().to_string())
.filter(|s| !s.is_empty())
.collect()
}
fn join_path(paths: &[String]) -> String {
pub(crate) fn join_path(paths: &[String]) -> String {
paths
.iter()
.map(|p| p.trim())
+2 -2
View File
@@ -259,8 +259,8 @@ export const useAppStore = create<AppState>((set, get) => ({
if (!window.confirm('PATH 长度超过建议值,是否继续保存?')) { set({ isSaving: false }); return; }
}
// 备份(失败时通知用户
invoke('backup_registry', { customDir: null, sysPaths, userPaths })
// 备份当前注册表(保存前备份旧值,失败仅警告不中断
invoke('backup_registry', { customDir: null })
.catch(() => set({ statusMessage: i18n.t('status.warning_backup') }));
const [sysResult, userResult] = await Promise.allSettled([