如题,从 【无用软件】sc_starter,ScreenCapture的快捷键增强 开始继续掰扯
目的
防止软件多开
可行的部分思路
- 文件锁
- 线程互斥锁(只会抄C++,rust没有能直接抄的代码……)
- 管道
- 邪门办法
我的邪门办法(其实算是低级文件锁吧大概)
- 程序启动时自动创建一个时间文件(精确到秒)
- 同时循环移除其他创建时间较早的时间文件
代码
fn get_time(config_dir: &PathBuf) -> PathBuf {
//获取当前系统秒数并创建文件,同时如果有旧的删除旧的,为实现单实例做准备
let seconds = match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
Ok(n) => String::from("TIME") + n.as_secs().to_string().as_str(),
Err(_) => String::from("0"),
};
let time_check_file = config_dir.join(&seconds);
if !time_check_file.exists() {
match fs::File::create(&time_check_file) {
Ok(_) => true,
Err(_) => panic!("No permissions."),
};
} else {
exit(-1);
}
//遍历配置文件夹中的文件
let mut time_file_nums: Vec<u64> = Vec::new();
for entry in fs::read_dir(config_dir).unwrap() {
let path = entry.unwrap().path();
let name = path.file_stem().unwrap().to_str().unwrap();
if name.starts_with("TIME") {
time_file_nums.push((name.split_at(4).1).parse::<u64>().unwrap());
}
}
while time_file_nums.len() > 1 {
if time_file_nums[0] < time_file_nums[1] {
let _ = fs::remove_file(config_dir.join(format!("{}{}", "TIME", time_file_nums[0])))
.unwrap();
time_file_nums.remove(0);
} else {
let _ = fs::remove_file(config_dir.join(format!("{}{}", "TIME", time_file_nums[1])))
.unwrap();
time_file_nums.remove(1);
}
}
time_check_file
}
- 采用多线程,一个线程执行主任务,另一个线程定期对上述时间文件是否存在进行检测
- 如果不存在则退出程序
代码
fn avoid_multiple(check_file: &PathBuf) -> JoinHandle<()> {
//避免多开,仍然不是很完善……
let file_path = check_file.clone();
let handle = thread::spawn(move || loop {
if file_path.exists() {
thread::sleep(time::Duration::from_secs(1))
} else {
exit(-1);
}
});
handle
}
预想中的运行
- 如果同时打开了多次程序因为创建文件失败自动退出,只留一个
- 如果间隔一阵子再打开一次程序,则通过1s一次的查询自动退出之前的程序并以新程序为主体重新注册快捷键
存在的问题
- 时间间隔太长,但是时间短了以后cpu占用又高(无法接受0.1%以上的cpu占用)
- 极端情况无法完美应对:用户在1s,2s时分别打开了一次程序,由于程序是2s后才会注册快捷键,且1s遍历一次,因此可能会出现至多1s的时间使软件多开为2个
- 启动时间长,2s以后程序才会响应快捷键还不慢吗……
- 无法加速启动速度。如上所言,加速启动速度就必然意味着cpu占用升高……
- 在CPU占满、磁盘性能极低等极端情况下无法较好响应。因为是文件锁,且需要遍历文件夹,因此如果用户往文件夹里面恶意塞文件或者磁盘性能极低导致遍历时间远超1s,那这个代码就完全废了……
理论上的改进办法
- 换正规办法,如线程互斥锁(废话,这不是不会吗)
- 换新电脑然后把循环时间改成200ms……这样cpu占用还是<0.1%……