mirror of
https://github.com/LHY0125/PathEditor.git
synced 2026-06-29 01:45:54 +08:00
fix: backup_registry 改为内部读取注册表当前值,不再依赖前端传入数据
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use std::fs;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
fn backup_base_dir() -> PathBuf {
|
fn backup_base_dir() -> PathBuf {
|
||||||
@@ -17,27 +16,41 @@ pub fn get_appdata_dir() -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// 备份当前注册表中的系统 PATH 和用户 PATH
|
/// 备份当前注册表中的系统 PATH 和用户 PATH
|
||||||
/// 返回备份文件的路径
|
/// 在保存前调用,备份的是注册表中的当前值(保存前的状态)
|
||||||
#[tauri::command]
|
#[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 {
|
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(),
|
_ => backup_base_dir(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// 创建目录
|
std::fs::create_dir_all(&backup_dir)
|
||||||
fs::create_dir_all(&backup_dir)
|
|
||||||
.map_err(|e| format!("无法创建备份目录: {}", e))?;
|
.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 timestamp = Local::now().format("%Y%m%d_%H%M%S_%3f");
|
||||||
let filename = format!("path_backup_{}.txt", timestamp);
|
let filename = format!("path_backup_{}.txt", timestamp);
|
||||||
let filepath = backup_dir.join(&filename);
|
let filepath = backup_dir.join(&filename);
|
||||||
|
|
||||||
// 写入备份内容
|
|
||||||
let mut content = String::new();
|
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");
|
content.push_str("\n[System PATH]\n");
|
||||||
for path in &sys_paths {
|
for path in &sys_paths {
|
||||||
content.push_str(&format!("{}\n", path));
|
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));
|
content.push_str(&format!("{}\n", path));
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::write(&filepath, &content)
|
std::fs::write(&filepath, &content)
|
||||||
.map_err(|e| format!("无法写入备份文件: {}", e))?;
|
.map_err(|e| format!("无法写入备份文件: {}", e))?;
|
||||||
|
|
||||||
let result = filepath.to_string_lossy().to_string();
|
let result = filepath.to_string_lossy().to_string();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const SYS_REG_PATH: &str = "SYSTEM\\CurrentControlSet\\Control\\Session Manager\
|
|||||||
const USER_REG_PATH: &str = "Environment";
|
const USER_REG_PATH: &str = "Environment";
|
||||||
const PATH_VALUE: &str = "Path";
|
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 key = RegKey::predef(root);
|
||||||
let env_key = key
|
let env_key = key
|
||||||
.open_subkey_with_flags(sub_path, KEY_READ)
|
.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))
|
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);
|
let value = join_path(paths);
|
||||||
|
|
||||||
// Windows 注册表 REG_EXPAND_SZ 上限 32767 字符
|
// 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)
|
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(';')
|
raw.split(';')
|
||||||
.map(|s| s.trim().to_string())
|
.map(|s| s.trim().to_string())
|
||||||
.filter(|s| !s.is_empty())
|
.filter(|s| !s.is_empty())
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn join_path(paths: &[String]) -> String {
|
pub(crate) fn join_path(paths: &[String]) -> String {
|
||||||
paths
|
paths
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p.trim())
|
.map(|p| p.trim())
|
||||||
|
|||||||
@@ -259,8 +259,8 @@ export const useAppStore = create<AppState>((set, get) => ({
|
|||||||
if (!window.confirm('PATH 长度超过建议值,是否继续保存?')) { set({ isSaving: false }); return; }
|
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') }));
|
.catch(() => set({ statusMessage: i18n.t('status.warning_backup') }));
|
||||||
|
|
||||||
const [sysResult, userResult] = await Promise.allSettled([
|
const [sysResult, userResult] = await Promise.allSettled([
|
||||||
|
|||||||
Reference in New Issue
Block a user