|
| 1 | +use std::{path::Path, process::Command}; |
| 2 | + |
1 | 3 | use anyhow::Result; |
2 | 4 | use rand::{Rng, distributions::Alphanumeric}; |
3 | 5 | use serde::Deserialize; |
@@ -314,17 +316,13 @@ pub async fn launch(app: AppHandle, launcher_id: i64) -> Result<(), OneClickLaun |
314 | 316 |
|
315 | 317 | let mut resources = launcher_resource::query_by_launcher_id(&db.pool, launcher_id).await?; |
316 | 318 |
|
| 319 | + tracing::debug!("启动编组原始资源列表: {resources:?}"); |
| 320 | + |
317 | 321 | // 必须从启动资源中排除自己,防止出现死循环 |
318 | 322 | let app_path = current_exe_path_str()?; |
319 | 323 | resources.retain(|e| { |
320 | | - // 检查路径是否包含空格 |
321 | | - if e.path.contains(' ') { |
322 | | - // 按空格拆分并取第一个部分进行比较 |
323 | | - e.path.split_whitespace().next() == Some(&app_path) |
324 | | - } else { |
325 | | - // 不包含空格时直接比较 |
326 | | - e.path.eq(&app_path) |
327 | | - } |
| 324 | + // 检查路径是否指向当前应用程序 |
| 325 | + !e.path.starts_with(&app_path) |
328 | 326 | }); |
329 | 327 |
|
330 | 328 | if resources.is_empty() { |
@@ -372,12 +370,48 @@ pub fn launch_resources(app: &AppHandle, resources: &[LauncherResource]) { |
372 | 370 | /// - `Ok(())` 表示操作成功。 |
373 | 371 | /// - `Err(OneClickLaunchError)` 表示操作失败。 |
374 | 372 | pub fn open_using_default_program(app: &AppHandle, path: &str) -> Result<(), OneClickLaunchError> { |
| 373 | + match try_open_as_command(path) { |
| 374 | + Ok(true) => return Ok(()), // 已经作为程序执行 |
| 375 | + Ok(false) => { |
| 376 | + // 不是程序,交给 opener |
| 377 | + open_path_with_opener(app, path)?; |
| 378 | + } |
| 379 | + Err(e) => { |
| 380 | + tracing::debug!("作为命令执行失败: {e:?},尝试默认打开"); |
| 381 | + open_path_with_opener(app, path)?; |
| 382 | + } |
| 383 | + } |
| 384 | + |
| 385 | + Ok(()) |
| 386 | +} |
| 387 | + |
| 388 | +fn open_path_with_opener(app: &AppHandle, path: &str) -> Result<(), OneClickLaunchError> { |
375 | 389 | app.opener() |
376 | 390 | .open_path(path, None::<&str>) |
377 | 391 | .map_err(|e| OneClickLaunchError::ExecutionError(e.to_string()))?; |
378 | 392 | Ok(()) |
379 | 393 | } |
380 | 394 |
|
| 395 | +fn try_open_as_command(path: &str) -> Result<bool, OneClickLaunchError> { |
| 396 | + let parts = shlex::split(path) |
| 397 | + .ok_or_else(|| OneClickLaunchError::ExecutionError("无法解析路径".to_string()))?; |
| 398 | + |
| 399 | + if parts.is_empty() { |
| 400 | + return Ok(false); |
| 401 | + } |
| 402 | + |
| 403 | + let program = &parts[0]; |
| 404 | + let args = &parts[1..]; |
| 405 | + |
| 406 | + // 如果第一个部分是存在的文件(.exe/.bat/.sh 等),才当成命令执行 |
| 407 | + if Path::new(program).exists() { |
| 408 | + Command::new(program).args(args).spawn()?; |
| 409 | + return Ok(true); |
| 410 | + } |
| 411 | + |
| 412 | + Ok(false) |
| 413 | +} |
| 414 | + |
381 | 415 | #[tauri::command] |
382 | 416 | pub async fn create_handler_shortcut( |
383 | 417 | launcher_id: i64, |
|
0 commit comments