use tauri-plugin-autostart

This commit is contained in:
VirtualHotBar
2024-06-04 11:24:20 +08:00
parent 3e51e2906c
commit ef47ae76e0
7 changed files with 164 additions and 218 deletions

51
src-tauri/Cargo.lock generated
View File

@@ -101,6 +101,7 @@ dependencies = [
"tar",
"tauri",
"tauri-build",
"tauri-plugin-autostart",
"tauri-plugin-fs",
"tauri-plugin-os",
"tauri-plugin-process",
@@ -295,6 +296,17 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "auto-launch"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f012b8cc0c850f34117ec8252a44418f2e34a2cf501de89e29b241ae5f79471"
dependencies = [
"dirs 4.0.0",
"thiserror",
"winreg 0.10.1",
]
[[package]]
name = "autocfg"
version = "1.3.0"
@@ -904,13 +916,22 @@ dependencies = [
"subtle",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys 0.3.7",
]
[[package]]
name = "dirs"
version = "5.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
dependencies = [
"dirs-sys",
"dirs-sys 0.4.1",
]
[[package]]
@@ -923,6 +944,17 @@ dependencies = [
"dirs-sys-next",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "dirs-sys"
version = "0.4.1"
@@ -4190,6 +4222,21 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tauri-plugin-autostart"
version = "2.0.0-beta.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59f0c8ed07512164ce45d8c05b42def923da8ead753ebded7b74fe4c5cd99021"
dependencies = [
"auto-launch",
"log",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"thiserror",
]
[[package]]
name = "tauri-plugin-fs"
version = "2.0.0-beta.9"
@@ -4674,7 +4721,7 @@ dependencies = [
"cocoa",
"core-graphics",
"crossbeam-channel",
"dirs",
"dirs 5.0.1",
"libappindicator",
"muda",
"objc",

View File

@@ -47,7 +47,7 @@ tauri-plugin-shell = "2.0.0-beta.7"
tauri-plugin-os = "2.0.0-beta.6"
tauri-plugin-fs = "2.0.0-beta.9"
tauri-plugin-process = "2.0.0-beta.6"
# tauri-plugin-autostart = "2.0.0-beta.7"
tauri-plugin-autostart = "2.0.0-beta.7"
tauri-plugin-single-instance = "2.0.0-beta.9"
[target.'cfg(windows)'.dependencies]
winreg = "0.10.1"

File diff suppressed because one or more lines are too long

View File

@@ -2422,6 +2422,54 @@
"app:deny-version"
]
},
{
"type": "string",
"enum": [
"autostart:default"
]
},
{
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:allow-disable"
]
},
{
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:allow-enable"
]
},
{
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:allow-is-enabled"
]
},
{
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:deny-disable"
]
},
{
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:deny-enable"
]
},
{
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:deny-is-enabled"
]
},
{
"description": "event:default -> Default permissions for the plugin.",
"type": "string",

View File

@@ -2422,6 +2422,54 @@
"app:deny-version"
]
},
{
"type": "string",
"enum": [
"autostart:default"
]
},
{
"description": "autostart:allow-disable -> Enables the disable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:allow-disable"
]
},
{
"description": "autostart:allow-enable -> Enables the enable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:allow-enable"
]
},
{
"description": "autostart:allow-is-enabled -> Enables the is_enabled command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:allow-is-enabled"
]
},
{
"description": "autostart:deny-disable -> Denies the disable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:deny-disable"
]
},
{
"description": "autostart:deny-enable -> Denies the enable command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:deny-enable"
]
},
{
"description": "autostart:deny-is-enabled -> Denies the is_enabled command without any pre-configured scope.",
"type": "string",
"enum": [
"autostart:deny-is-enabled"
]
},
{
"description": "event:default -> Default permissions for the plugin.",
"type": "string",

View File

@@ -1,205 +0,0 @@
use std::env;
use std::io;
#[cfg(target_os = "macos")]
pub fn set_autostart(enabled: bool) -> io::Result<()> {
use std::fs::File;
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::path::Path;
let label = "com.vhbs.netmount"; // 你的程序标识符
let exe_path = env::current_exe()?;
let exe_path_str = exe_path.to_string_lossy().into_owned();
let plist_content = if enabled {
let program_arguments = format!("\"{}\"", exe_path_str);
format!(
r#"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>{}</string>
<key>ProgramArguments</key>
<array>
<string>{}</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
</dict>
</plist>
"#,
label, program_arguments
)
} else {
"".to_string() // 如果禁用自启动则不需要创建plist文件
};
let plist_path_str = format!(
"{}/Library/LaunchAgents/{}.plist",
std::env::var("HOME").expect("HOME is not set"),
label
);
if !plist_content.is_empty() {
let plist_path = Path::new(&plist_path_str);
// 创建或覆盖plist文件
let mut file = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(plist_path)?;
// 使用let绑定创建一个较长生命周期的变量
let mut file = file; // 重新绑定以保持借用有效
file.write_all(plist_content.as_bytes())?;
std::process::Command::new("launchctl")
.arg("load")
.arg(plist_path_str)
.status()?;
}
Ok(())
}
#[cfg(target_os = "macos")]
pub fn is_autostart() -> io::Result<bool> {
let label = "com.vhbs.netmount"; // 你的程序标识符
let output = std::process::Command::new("launchctl")
.arg("list")
.arg(label)
.output()?;
if output.status.success() {
Ok(String::from_utf8_lossy(&output.stdout).contains(label))
} else {
Ok(false)
}
}
#[cfg(target_os = "windows")]
pub fn set_autostart(enabled: bool) -> io::Result<()> {
use std::{os::windows::process::CommandExt, process::Command};
let exe_path = env::current_exe()?;
let exe_path_str = exe_path.to_string_lossy().into_owned();
let command = if enabled {
format!(
"reg add HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v NetMount /t REG_SZ /d \"{}\" /f",
exe_path_str
)
} else {
"reg delete HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run /v NetMount /f"
.to_string()
};
let cmd = Command::new("cmd")
.arg("/C")
.arg(command.clone())
.creation_flags(0x08000000)
.spawn();
let output = cmd.unwrap().wait_with_output()?;
if output.status.success() {
Ok(())
} else {
Err(io::Error::new(
io::ErrorKind::Other,
format!(
"Failed to modify autostart setting. Command: '{}', Error: {}",
command,
String::from_utf8_lossy(&output.stderr)
),
))
}
}
#[cfg(target_os = "windows")]
pub fn is_autostart() -> io::Result<bool> {
extern crate winreg;
use winreg::enums::*;
use winreg::RegKey;
let app_name = "NetMount";
let exe_path = env::current_exe()?;
let exe_path_str = exe_path.to_string_lossy().into_owned();
// 打开注册表的“Run”键
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let run_key = hkcu.open_subkey("Software\\Microsoft\\Windows\\CurrentVersion\\Run")?;
// 尝试获取传入的app_name的值
match run_key.get_value::<String, _>(app_name) {
Ok(path) => Ok(path == format!("\"{}\"", exe_path_str)), // 如果成功获取值返回true
Err(_) => Ok(false), // 如果获取失败返回false
}
}
#[cfg(target_os = "linux")]
pub fn set_autostart(enabled: bool) -> io::Result<()> {
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
let exe_path = env::current_exe()?;
let exe_path_str = exe_path
.to_str()
.ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Failed to read executable path"))?;
const SERVICE_FILE_PATH: &str = "/etc/systemd/system/netmount.service";
if enabled {
// Create the service file
let service_content = format!(
"[Unit]
Description=NetMount
[Service]
ExecStart={}
Restart=always
User=root
Group=root
[Install]
WantedBy=multi-user.target
",
exe_path_str,
);
let mut file = File::create(SERVICE_FILE_PATH)?;
file.write_all(service_content.as_bytes())?;
println!("Service file created at {}", SERVICE_FILE_PATH);
// Inform the user about the need to manually run systemctl commands
println!("Please execute the following commands to enable and start the service:");
println!("sudo systemctl daemon-reload");
println!("sudo systemctl enable --now netmount");
Ok(())
} else {
// Remove the service file if it exists
if Path::new(SERVICE_FILE_PATH).exists() {
std::fs::remove_file(SERVICE_FILE_PATH)?;
println!("Service file removed.");
} else {
println!("Service file does not exist; no action taken.");
}
Ok(())
}
}
#[cfg(target_os = "linux")]
pub fn is_autostart() -> io::Result<bool> {
use std::path::Path;
let file_path = format!("/etc/systemd/system/{}.service", "netmount");
Ok(Path::new(&file_path).exists())
}

View File

@@ -5,20 +5,19 @@ use std::path::PathBuf;
use std::{env, fs::File, ops::Deref, path::Path, sync::RwLock};
use config::Config;
use fs::{fs_exist_dir, fs_make_dir,read_json_file,write_json_file};
use fs::{fs_exist_dir, fs_make_dir, read_json_file, write_json_file};
use locale::Locale;
use tray::Tray;
mod autostart;
mod config;
mod fs;
mod locale;
mod tray;
mod utils;
use crate::autostart::is_autostart;
use crate::autostart::set_autostart;
use crate::utils::download_with_progress;
use tauri_plugin_autostart::MacosLauncher;
use tauri_plugin_autostart::ManagerExt;
// use crate::utils::ensure_single_instance;
#[cfg(target_os = "windows")]
use crate::utils::find_first_available_drive_letter;
@@ -180,6 +179,10 @@ pub fn init() -> anyhow::Result<()> {
.plugin(tauri_plugin_single_instance::init(|app, _, _| {
app.app_main_window().toggle_visibility(Some(true)).ok();
}))
.plugin(tauri_plugin_autostart::init(
MacosLauncher::LaunchAgent,
Some(vec![]),
))
.invoke_handler(tauri::generate_handler![
toggle_devtools,
get_config,
@@ -261,17 +264,22 @@ fn get_winfsp_install_state() -> Result<bool, usize> {
}
#[tauri::command]
fn get_autostart_state() -> Result<bool, usize> {
match is_autostart() {
fn get_autostart_state(app: tauri::AppHandle<Runtime>) -> Result<bool, usize> {
let autostart_manager = app.autolaunch();
match autostart_manager.is_enabled() {
Ok(is_enabled) => Ok(is_enabled),
Err(_) => Ok(false),
}
}
#[tauri::command]
fn set_autostart_state(enabled: bool) -> Result<(), ()> {
let _ = set_autostart(enabled);
Ok(())
fn set_autostart_state(app: tauri::AppHandle<Runtime>, enabled: bool) -> Result<bool, ()> {
let autostart_manager = app.autolaunch();
Ok(if enabled {
autostart_manager.enable().is_ok()
} else {
autostart_manager.disable().is_ok()
})
}
#[tauri::command]