# auto-launch ## 项目概述 跨平台应用开机自启动库,支持 Windows、macOS 和 Linux。 **GitHub**: https://github.com/zzzgydi/auto-launch.git **本地路径**: `vendors/auto-launch` ## 目录结构 ``` auto-launch/ ├── src/ │ ├── lib.rs # 公共 API │ ├── windows.rs # Windows 实现 │ ├── macos.rs # macOS 实现 │ ├── linux.rs # Linux 实现 │ └── error.rs # 错误处理 ├── Cargo.toml └── README.md ``` ## 核心依赖 ```toml [dependencies] thiserror = "1.0" os_info = "7.0" # Windows windows-registry = "0.2" windows-result = "0.2" # macOS smappservice-rs = "0.3" # Linux dirs = "5.0" ``` ## 核心 API ### AutoLaunchBuilder ```rust // lib.rs pub struct AutoLaunchBuilder { app_name: Option, app_path: Option, macos_launch_mode: MacOSLaunchMode, bundle_identifiers: Option>, agent_extra_config: Option, windows_enable_mode: WindowsEnableMode, linux_launch_mode: LinuxLaunchMode, args: Option>, } impl AutoLaunchBuilder { pub fn new() -> Self; /// 设置应用名称 pub fn set_app_name(&mut self, name: &str) -> &mut Self; /// 设置应用路径 pub fn set_app_path(&mut self, path: &str) -> &mut Self; /// 设置 macOS 启动模式 pub fn set_macos_launch_mode(&mut self, mode: MacOSLaunchMode) -> &mut Self; /// 设置 Windows 启用模式 pub fn set_windows_enable_mode(&mut self, mode: WindowsEnableMode) -> &mut Self; /// 设置 Linux 启动模式 pub fn set_linux_launch_mode(&mut self, mode: LinuxLaunchMode) -> &mut Self; /// 设置启动参数 pub fn set_args(&mut self, args: &[impl AsRef]) -> &mut Self; /// 构建 AutoLaunch pub fn build(&self) -> Result; } ``` ### AutoLaunch ```rust pub struct AutoLaunch { app_name: String, app_path: String, args: Vec, // 平台特定配置... } impl AutoLaunch { /// 启用自启动 pub async fn enable(&self) -> Result<()>; /// 禁用自启动 pub async fn disable(&self) -> Result<()>; /// 检查是否已启用 pub async fn is_enabled(&self) -> Result; } ``` ### 平台特定枚举 ```rust pub enum MacOSLaunchMode { /// 使用 SMAppService (macOS 13+) SMAppService, /// 使用 LaunchAgent LaunchAgent, /// 使用 AppleScript AppleScript, } pub enum WindowsEnableMode { /// 动态尝试(系统级 -> 用户级) Dynamic, /// 仅当前用户 CurrentUser, /// 所有用户(需管理员权限) System, } pub enum LinuxLaunchMode { /// 使用 XDG Autostart XdgAutostart, /// 使用 systemd Systemd, } ``` ## 使用示例 ```rust use auto_launch::AutoLaunch; #[tokio::main] async fn main() -> Result<()> { let auto = AutoLaunchBuilder::new() .set_app_name("qiming-agent") .set_app_path("/Applications/qiming-agent.app") .set_args(&["--hidden", "--minimize"]) .set_macos_launch_mode(MacOSLaunchMode::SMAppService) .build()?; // 检查是否已启用 let is_enabled = auto.is_enabled().await?; println!("Auto launch enabled: {}", is_enabled); // 启用自启动 if !is_enabled { auto.enable().await?; } Ok(()) } ``` ## 平台实现 | 平台 | 实现方式 | 配置位置 | |------|----------|----------| | Windows | 注册表 | `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` | | macOS | SMAppService | `~/Library/LaunchAgents/` | | Linux | XDG | `~/.config/autostart/` | ## 与 agent-client 集成场景 ### 场景1:设置界面的自启动开关 ```rust // 在设置界面中集成自启动管理 use auto_launch::{AutoLaunch, AutoLaunchBuilder, MacOSLaunchMode}; pub struct AutoLaunchManager { auto_launch: AutoLaunch, // 当前状态(缓存,避免频繁读取) cached_enabled: bool, } impl AutoLaunchManager { pub fn new(app_name: &str, app_path: &str) -> Result { let auto = AutoLaunchBuilder::new() .set_app_name(app_name) .set_app_path(app_path) .set_macos_launch_mode(MacOSLaunchMode::SMAppService) // macOS 13+ .build()?; Ok(Self { auto_launch: auto, cached_enabled: false, }) } /// 获取当前自启动状态 pub async fn is_enabled(&self) -> Result { self.auto_launch.is_enabled().await } /// 启用自启动 pub async fn enable(&self) -> Result<()> { self.auto_launch.enable().await } /// 禁用自启动 pub async fn disable(&self) -> Result<()> { self.auto_launch.disable().await } /// 切换自启动状态 pub async fn toggle(&self) -> Result { let enabled = self.is_enabled().await?; if enabled { self.disable().await?; } else { self.enable().await?; } Ok(!enabled) } } /// 设置界面中的自启动开关组件 pub struct AutoLaunchSwitch { manager: AutoLaunchManager, enabled: bool, loading: bool, } impl AutoLaunchSwitch { pub fn new(manager: AutoLaunchManager) -> Self { Self { manager, enabled: false, loading: true, } } /// 初始化时检查状态 pub fn refresh_status(&mut self) { let manager = self.manager.clone(); cx.spawn(|this, mut cx| async move { let enabled = manager.is_enabled().await.unwrap_or(false); this.update(&mut cx, |this, _| { this.enabled = enabled; this.loading = false; }); }); } } impl Render for AutoLaunchSwitch { fn render(&mut self, cx: &mut ViewContext) -> impl IntoElement { div() .flex() .items_center() .justify_between() .p_4() .rounded_md() .bg(cx.theme().colors.surface) .border_1() .border_color(cx.theme().colors.border) .child( div() .flex() .flex_col() .gap_1() .child( div() .font_medium() .child("Auto Launch") ) .child( div() .text_sm() .text_color(cx.theme().colors.muted) .child("Start application when system boots") ) ) .child( match self.loading { true => Loading::new().into_any_element(), false => Switch::new(self.enabled, |enabled, _| { // 切换自启动 let manager = self.manager.clone(); cx.spawn(|this, mut cx| async move { let result = if enabled { manager.disable().await } else { manager.enable().await }; match result { Ok(_) => { this.update(&mut cx, |this, _| { this.enabled = !enabled; }); } Err(e) => { // 显示错误提示 tracing::error!("Failed to toggle auto-launch: {}", e); } } }); }).into_any_element(), } ) } } ``` ### 场景2:应用启动时检查自启动状态 ```rust // 应用启动时的初始化逻辑 pub struct AppInitializer { auto_launch_manager: Option, } impl AppInitializer { pub async fn initialize(&mut self, app_path: &str) -> Result<()> { // 1. 初始化自启动管理器 self.auto_launch_manager = Some( AutoLaunchManager::new("qiming-agent", app_path).ok() ); // 2. 检查自启动是否已启用 if let Some(manager) = &self.auto_launch_manager { let is_enabled = manager.is_enabled().await.unwrap_or(false); tracing::info!("Auto-launch enabled: {}", is_enabled); } // 3. 根据启动参数决定行为 let args: Vec = std::env::args().collect(); // 如果是通过自启动触发的,可能需要最小化到托盘 if args.iter().any(|arg| arg == "--minimize") { // 最小化到托盘,不显示主窗口 } Ok(()) } } ``` ### 场景3:跨平台注意事项 ```rust // 不同平台的自启动行为差异处理 #[cfg(target_os = "windows")] mod windows_impl { use auto_launch::WindowsEnableMode; pub fn get_app_path() -> String { // Windows: 使用完整路径 std::env::current_exe() .unwrap() .to_string_lossy() .into_owned() } pub fn build_auto_launch(name: &str, path: &str) -> auto_launch::AutoLaunchBuilder { AutoLaunchBuilder::new() .set_app_name(name) .set_app_path(path) .set_windows_enable_mode(WindowsEnableMode::CurrentUser) // 当前用户 } } #[cfg(target_os = "macos")] mod macos_impl { use auto_launch::MacOSLaunchMode; pub fn get_app_path() -> String { // macOS: 使用 .app 路径 std::env::current_exe() .unwrap() .to_string_lossy() .into_owned() } pub fn build_auto_launch(name: &str, path: &str) -> auto_launch::AutoLaunchBuilder { AutoLaunchBuilder::new() .set_app_name(name) .set_app_path(path) .set_macos_launch_mode(MacOSLaunchMode::SMAppService) // macOS 13+ } } #[cfg(target_os = "linux")] mod linux_impl { use auto_launch::LinuxLaunchMode; pub fn get_app_path() -> String { std::env::current_exe() .unwrap() .to_string_lossy() .into_owned() } pub fn build_auto_launch(name: &str, path: &str) -> auto_launch::AutoLaunchBuilder { AutoLaunchBuilder::new() .set_app_name(name) .set_app_path(path) .set_linux_launch_mode(LinuxLaunchMode::XdgAutostart) } } ``` ## 在本项目中的使用 用于实现 agent-client 的开机自启动功能: ``` agent-client │ └── auto-launch │ ├── 检测自启动状态 (设置界面开关) ├── 启用自启动 (用户勾选开关) ├── 禁用自启动 (用户取消勾选) └── 应用启动时最小化到托盘 ```