From 6b021658ad514255c7398983b088c1636caaa5e4 Mon Sep 17 00:00:00 2001 From: Filip <34747899+neriousy@users.noreply.github.com> Date: Thu, 26 Feb 2026 09:39:55 +0100 Subject: [PATCH] fix(app): open in powershell (#15112) --- packages/desktop/src-tauri/src/lib.rs | 15 ++++++++- packages/desktop/src-tauri/src/os/windows.rs | 32 +++++++++++++++++--- packages/desktop/src/bindings.ts | 1 + packages/desktop/src/index.tsx | 11 ++++++- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/packages/desktop/src-tauri/src/lib.rs b/packages/desktop/src-tauri/src/lib.rs index 71fe8407f..879732121 100644 --- a/packages/desktop/src-tauri/src/lib.rs +++ b/packages/desktop/src-tauri/src/lib.rs @@ -179,6 +179,18 @@ fn resolve_app_path(app_name: &str) -> Option { } } +#[tauri::command] +#[specta::specta] +fn open_in_powershell(path: String) -> Result<(), String> { + #[cfg(target_os = "windows")] + { + return os::windows::open_in_powershell(path); + } + + #[cfg(not(target_os = "windows"))] + Err("PowerShell is only supported on Windows".to_string()) +} + #[cfg(target_os = "macos")] fn check_macos_app(app_name: &str) -> bool { // Check common installation locations @@ -373,7 +385,8 @@ fn make_specta_builder() -> tauri_specta::Builder { markdown::parse_markdown_command, check_app_exists, wsl_path, - resolve_app_path + resolve_app_path, + open_in_powershell ]) .events(tauri_specta::collect_events![ LoadingWindowComplete, diff --git a/packages/desktop/src-tauri/src/os/windows.rs b/packages/desktop/src-tauri/src/os/windows.rs index cab265b62..a163c4aa7 100644 --- a/packages/desktop/src-tauri/src/os/windows.rs +++ b/packages/desktop/src-tauri/src/os/windows.rs @@ -6,9 +6,12 @@ use std::{ }; use windows_sys::Win32::{ Foundation::ERROR_SUCCESS, - System::Registry::{ - HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, REG_EXPAND_SZ, REG_SZ, RRF_RT_REG_EXPAND_SZ, - RRF_RT_REG_SZ, RegGetValueW, + System::{ + Registry::{ + RegGetValueW, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE, REG_EXPAND_SZ, REG_SZ, + RRF_RT_REG_EXPAND_SZ, RRF_RT_REG_SZ, + }, + Threading::{CREATE_NEW_CONSOLE, CREATE_NO_WINDOW}, }, }; @@ -310,7 +313,7 @@ pub fn resolve_windows_app_path(app_name: &str) -> Option { let resolve_where = |query: &str| -> Option { let output = Command::new("where") - .creation_flags(0x08000000) + .creation_flags(CREATE_NO_WINDOW) .arg(query) .output() .ok()?; @@ -437,3 +440,24 @@ pub fn resolve_windows_app_path(app_name: &str) -> Option { None } + +pub fn open_in_powershell(path: String) -> Result<(), String> { + let path = PathBuf::from(path); + let dir = if path.is_dir() { + path + } else if let Some(parent) = path.parent() { + parent.to_path_buf() + } else { + std::env::current_dir() + .map_err(|e| format!("Failed to determine current directory: {e}"))? + }; + + Command::new("powershell.exe") + .creation_flags(CREATE_NEW_CONSOLE) + .current_dir(dir) + .args(["-NoExit"]) + .spawn() + .map_err(|e| format!("Failed to start PowerShell: {e}"))?; + + Ok(()) +} diff --git a/packages/desktop/src/bindings.ts b/packages/desktop/src/bindings.ts index 6d05bfc56..8e1b4127a 100644 --- a/packages/desktop/src/bindings.ts +++ b/packages/desktop/src/bindings.ts @@ -18,6 +18,7 @@ export const commands = { checkAppExists: (appName: string) => __TAURI_INVOKE("check_app_exists", { appName }), wslPath: (path: string, mode: "windows" | "linux" | null) => __TAURI_INVOKE("wsl_path", { path, mode }), resolveAppPath: (appName: string) => __TAURI_INVOKE("resolve_app_path", { appName }), + openInPowershell: (path: string) => __TAURI_INVOKE("open_in_powershell", { path }), }; /** Events */ diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index 983fe3945..188a37eb8 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -118,7 +118,6 @@ const createPlatform = (): Platform => { async openPath(path: string, app?: string) { const os = ostype() if (os === "windows") { - const resolvedApp = (app && (await commands.resolveAppPath(app))) || app const resolvedPath = await (async () => { if (window.__OPENCODE__?.wsl) { const converted = await commands.wslPath(path, "windows").catch(() => null) @@ -127,6 +126,16 @@ const createPlatform = (): Platform => { return path })() + const resolvedApp = (app && (await commands.resolveAppPath(app))) || app + const isPowershell = (value?: string) => { + if (!value) return false + const name = value.toLowerCase().replaceAll("/", "\\").split("\\").pop() + return name === "powershell" || name === "powershell.exe" + } + if (isPowershell(resolvedApp)) { + await commands.openInPowershell(resolvedPath) + return + } return openerOpenPath(resolvedPath, resolvedApp) } return openerOpenPath(path, app)