From 6b7180527400a156e19fb99a8cdb1ac7b421e201 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 10 Apr 2024 21:12:28 +0800 Subject: [PATCH] optimize the opening item logic (solve the problem that some software/files cannot be opened, and too many running programs cause the program to crash). --- electron/main/commons/ipcEvent.ts | 3 +- electron/main/item/index.ts | 162 ++++++++++++++++++++------ rust/lib.rs | 27 ++--- rust/windows.rs | 97 ++------------- src/pages/item/components/Content.vue | 2 +- 5 files changed, 146 insertions(+), 145 deletions(-) diff --git a/electron/main/commons/ipcEvent.ts b/electron/main/commons/ipcEvent.ts index d0f35a3..2552b2d 100644 --- a/electron/main/commons/ipcEvent.ts +++ b/electron/main/commons/ipcEvent.ts @@ -11,6 +11,7 @@ import { } from "."; import { statSync } from "node:fs"; import { getWindow } from "../commons/index"; +import { execute } from "../item"; export default function () { // emit @@ -165,7 +166,7 @@ export default function () { }); // 运行 ipcMain.on("run", (event, args) => { - global.addon.shellExecute( + execute( args.operation, args.target, args.params ?? "", diff --git a/electron/main/item/index.ts b/electron/main/item/index.ts index dab3329..1078f62 100644 --- a/electron/main/item/index.ts +++ b/electron/main/item/index.ts @@ -1,5 +1,5 @@ import { BrowserWindow, shell, dialog, app } from "electron"; -import { join } from "node:path"; +import { join, dirname } from "node:path"; import { parsePath, getURLParams } from "../../commons/utils"; import { Item } from "../../../types/item"; import { @@ -11,7 +11,7 @@ import { updateData, updateOrder, } from "./data"; -import { accessSync, writeFile, statSync, readFileSync } from "node:fs"; +import { writeFile, statSync, readFileSync } from "node:fs"; import mime from "mime"; import { deleteExtname, @@ -27,6 +27,7 @@ import { sendToWebContent, } from "../commons/index"; import { fork } from "../../commons/utilityProcessUtils"; +import { exec } from "node:child_process"; // 窗口 let itemAddEditWindow: BrowserWindow | null = null; @@ -301,6 +302,58 @@ function updateOpenInfo(type: string, id: number) { } } +/** + * 运行 + * @param operation + * @param file + * @param params + * @param startLocation + */ +function execute( + operation: "open" | "runas", + file: string, + params: string | null, + startLocation: string | null = null +) { + // 工作目录 + let currentDir = startLocation; + if (!currentDir || currentDir.trim() === "") { + let statRes = statSync(file); + if (statRes.isDirectory()) { + currentDir = file; + } else { + currentDir = dirname(file); + } + } + // 组装命令 + let cmd: string; + if (operation === "open") { + cmd = 'start "" "' + file + '"'; + if (params && params.trim() !== "") { + let paramsList = analysisParams(params); + for (const param of paramsList) { + cmd += ' "' + param + '"'; + } + } + } else if (operation === "runas") { + cmd = "powershell Start-Process"; + cmd += " '\"" + file + "\"' "; + cmd += "-Verb RunAs"; + if (params && params.trim() !== "") { + cmd += " -ArgumentList "; + let paramsList = analysisParams(params); + for (let i = 0; i < paramsList.length; i++) { + if (i > 0) { + cmd += ", "; + } + cmd += "'\\\"" + paramsList[i] + "\\\"'"; + } + } + } + // 运行 + exec(cmd, { cwd: currentDir }); +} + /** * 运行项目 * @param type @@ -320,50 +373,88 @@ function run( // 网址 shell.openExternal(item.data.target); } else if (item.type === 3 || item.type === 4) { - // 系统 或 appx - global.addon.systemItemExecute(item.data.target, item.data.params); + if (item.data.target.indexOf("shell:") >= 0) { + // 带有shell: + exec("explorer " + item.data.target); + } else if (item.data.target === "static:TurnOffMonitor") { + // 关闭显示器 + global.addon.turnOffMonitor(); + } else { + if (item.type === 3) { + // 带路径的系统软件 + let path = global.addon.searchPath(item.data.target); + if (!path || path.trim() === "") { + path = item.data.target; + } + let cmd = 'start "" "' + path + '"'; + if (item.data.params && item.data.params.trim() !== "") { + let paramsList = analysisParams(item.data.params); + for (const param of paramsList) { + cmd += ' "' + param + '"'; + } + } + exec(cmd, { + cwd: app.getPath("home"), + }); + } else { + // appx + execute( + "open", + item.data.target, + item.data.params, + app.getPath("home") + ); + } + } } else { // 获取绝对路径 if (item.type === 0 || item.type === 1) { // 获取路径 item.data.target = parsePath(item.data.target); } - try { - // 判断文件或文件夹是否存在 - accessSync(item.data.target); - // 存在 - if (operation === "openFileLocation") { - // 打开文件所在位置 - global.addon.openFileLocation(item.data.target); - } else { - // 运行 - global.addon.shellExecute( - operation, - item.data.target, - item.data.params ?? "", - item.data.startLocation - ); - } - } catch (e) { - let message: string | null = null; - if (item.type === 0 && operation !== "openFileLocation") { - message = global.language.notFoundFile; - } else { - message = global.language.notFoundFolder; - } - message += '"' + item.data.target + '"'; - dialog.showMessageBox(global.mainWindow, { - title: "Dawn Launcher", - message: message, - buttons: [global.language.ok], - type: "error", - noLink: true, - }); + if (operation === "openFileLocation") { + // 打开文件所在位置 + global.addon.openFileLocation(item.data.target); + } else { + // 运行 + execute( + operation, + item.data.target, + item.data.params ?? "", + item.data.startLocation + ); } } } } +/** + * 解析参数 + * @param params + */ +function analysisParams(params: string) { + // res + let resParams = []; + // 尝试获取带有双引号的参数 + const values = params.trim().match(/"([^"]*)"/g); + // 添加到结果列表并替换掉原有字符串 + if (values) { + values.forEach((v) => { + resParams.push(v.replace(/"/g, "")); + params = params.replace(v, ""); + }); + } + // 按空格切分参数 + let split = params.trim().split(" "); + split.forEach((v) => { + if (v.trim() !== "") { + resParams.push(v); + } + }); + // 返回 + return resParams; +} + /** * 转换目标路径 * @param idList @@ -711,4 +802,5 @@ export { pasteIcon, checkInvalid, deleteQuickSearchHistory, + execute, }; diff --git a/rust/lib.rs b/rust/lib.rs index 7c18160..581d6f0 100644 --- a/rust/lib.rs +++ b/rust/lib.rs @@ -31,24 +31,6 @@ fn get_shortcut_file_info(path: String) -> Option> { windows::get_shortcut_file_info(&path) } -/** - * 运行 - */ -#[allow(dead_code)] -#[napi] -fn shell_execute(operation: String, file: String, params: String, start_location: Option) { - windows::shell_execute(operation, file, params, start_location) -} - -/** - * 运行系统项目 - */ -#[allow(dead_code)] -#[napi] -fn system_item_execute(target: String, params: Option) { - windows::system_item_execute(&target, params.as_deref()) -} - /** * 打开文件所在位置 */ @@ -192,3 +174,12 @@ fn get_appx_list() -> Vec> { fn get_cursor_point() -> [i32; 2] { windows::get_cursor_point() } + +/** + * 关闭显示器 + */ +#[allow(dead_code)] +#[napi] +pub fn turn_off_monitor() { + windows::turn_off_monitor() +} diff --git a/rust/windows.rs b/rust/windows.rs index 823908e..f5336b3 100644 --- a/rust/windows.rs +++ b/rust/windows.rs @@ -6,18 +6,15 @@ use napi::{ JsFunction, }; use serde::{Deserialize, Serialize}; -use std::thread; use std::{ collections::HashMap, io::Cursor, - path::Path, process::Command, sync::atomic::{AtomicBool, Ordering}, }; use windows::Management::Deployment::PackageManager; use windows::{ core::{ComInterface, HSTRING, PCSTR, PCWSTR}, - w, Win32::{ Foundation::{HWND, LPARAM, LRESULT, MAX_PATH, POINT, RECT, SIZE, WPARAM}, Graphics::{ @@ -34,7 +31,6 @@ use windows::{ CLSCTX_INPROC_SERVER, COINIT_APARTMENTTHREADED, STGM_READ, }, Environment::GetEnvironmentVariableW, - SystemInformation::GetSystemDirectoryW, }, UI::{ Input::Ime::{ @@ -44,19 +40,18 @@ use windows::{ Shell::{ BHID_SFUIObject, IContextMenu, IShellItem, IShellItemImageFactory, IShellLinkW, SHCreateItemFromParsingName, SHEmptyRecycleBinW, SHQueryUserNotificationState, - ShellExecuteW, ShellLink, CMF_NORMAL, CMINVOKECOMMANDINFO, - QUNS_ACCEPTS_NOTIFICATIONS, QUNS_APP, QUNS_BUSY, QUNS_NOT_PRESENT, - QUNS_PRESENTATION_MODE, QUNS_QUIET_TIME, QUNS_RUNNING_D3D_FULL_SCREEN, - SHERB_NOSOUND, SIIGBF_ICONONLY, SLGP_UNCPRIORITY, + ShellLink, CMF_NORMAL, CMINVOKECOMMANDINFO, QUNS_ACCEPTS_NOTIFICATIONS, QUNS_APP, + QUNS_BUSY, QUNS_NOT_PRESENT, QUNS_PRESENTATION_MODE, QUNS_QUIET_TIME, + QUNS_RUNNING_D3D_FULL_SCREEN, SHERB_NOSOUND, SIIGBF_ICONONLY, SLGP_UNCPRIORITY, }, WindowsAndMessaging::{ CallNextHookEx, CreatePopupMenu, DestroyMenu, FindWindowW, GetClassNameW, GetCursorPos, GetForegroundWindow, GetSystemMetrics, GetWindowRect, SendMessageW, SetForegroundWindow, SetWindowsHookExW, TrackPopupMenu, WindowFromPoint, HHOOK, - MSLLHOOKSTRUCT, SC_MONITORPOWER, SM_CXSCREEN, SM_CYSCREEN, SW_NORMAL, - SW_SHOWDEFAULT, TPM_NONOTIFY, TPM_RETURNCMD, WH_MOUSE_LL, WM_LBUTTONDOWN, - WM_LBUTTONUP, WM_MBUTTONDOWN, WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, - WM_MOUSEWHEEL, WM_RBUTTONDOWN, WM_RBUTTONUP, WM_SYSCOMMAND, + MSLLHOOKSTRUCT, SC_MONITORPOWER, SM_CXSCREEN, SM_CYSCREEN, SW_NORMAL, TPM_NONOTIFY, + TPM_RETURNCMD, WH_MOUSE_LL, WM_LBUTTONDOWN, WM_LBUTTONUP, WM_MBUTTONDOWN, + WM_MBUTTONUP, WM_MOUSEHWHEEL, WM_MOUSEMOVE, WM_MOUSEWHEEL, WM_RBUTTONDOWN, + WM_RBUTTONUP, WM_SYSCOMMAND, }, }, }, @@ -177,45 +172,6 @@ fn image_buffer_to_base64(image_buffer: ImageBuffer, Vec>) -> Strin ) } -/** - * 运行 - */ -pub fn shell_execute( - operation: String, - file: String, - params: String, - start_location: Option, -) { - thread::spawn(move || { - // dir - let dir = start_location.unwrap_or_else(|| { - // 判断是否是文件夹 - let path = Path::new(&file); - if path.is_dir() { - // 文件夹 - file.clone() - } else { - // 文件 获取上一级目录 - path.parent().unwrap().display().to_string() - } - }); - // HSTRING - let operation = HSTRING::from(operation.as_str()); - let file = HSTRING::from(file.as_str()); - let params = HSTRING::from(params.as_str()); - let dir = HSTRING::from(dir.as_str()); - // PCWSTR - let operation = PCWSTR(operation.as_ptr()); - let file = PCWSTR(file.as_ptr()); - let params = PCWSTR(params.as_ptr()); - let dir = PCWSTR(dir.as_ptr()); - unsafe { - // execute - ShellExecuteW(None, operation, file, params, dir, SW_SHOWDEFAULT); - } - }); -} - /** * 获取快捷方式信息 */ @@ -265,45 +221,6 @@ pub fn get_shortcut_file_info(path: &str) -> Option> { None } -/** - * 运行命令 - */ -pub fn system_item_execute(target: &str, params: Option<&str>) { - if target == "static:TurnOffMonitor" { - // 关闭显示器 - turn_off_monitor() - } else { - let mut file = target.to_string(); - if !target.starts_with("shell:") { - // 如果不是shell开头,就查询路径 - file = search_path(target).unwrap_or(target.to_string()); - } - let file = HSTRING::from(file); - let params = match params { - Some(p) => HSTRING::from(p), - _ => HSTRING::new(), - }; - // 获取系统盘路径当作工作目录 - let mut buffer = [0u16; MAX_PATH as usize]; - unsafe { - GetSystemDirectoryW(Some(&mut buffer)); - } - let dir = u16_to_string(&buffer); - let dir = HSTRING::from(dir); - // execute - unsafe { - ShellExecuteW( - None, - w!("open"), - PCWSTR(file.as_ptr()), - PCWSTR(params.as_ptr()), - PCWSTR(dir.as_ptr()), - SW_SHOWDEFAULT, - ); - } - } -} - /** * 关闭显示器 */ diff --git a/src/pages/item/components/Content.vue b/src/pages/item/components/Content.vue index d41f642..c851ab4 100644 --- a/src/pages/item/components/Content.vue +++ b/src/pages/item/components/Content.vue @@ -536,7 +536,7 @@ function drop(e: any, classificationId: number | null) { ) { // 如果不是同一个项目就可以使用某个程序打开此文件 if (item.id !== store.itemDragOutData.id) { - let params = store.itemDragOutData.data.target; + let params = '"' + store.itemDragOutData.data.target + '"'; if (item.data.params) { params += " " + item.data.params; }