diff --git a/src/Rust/src/windows/util.rs b/src/Rust/src/windows/util.rs index 3ac82dfe..4c463130 100644 --- a/src/Rust/src/windows/util.rs +++ b/src/Rust/src/windows/util.rs @@ -18,6 +18,7 @@ use windows::{ }, }; use winsafe::{self as w, co}; +use windows::Win32::UI::WindowsAndMessaging::AllowSetForegroundWindow; pub fn run_hook(app: &shared::bundle::Manifest, root_path: &PathBuf, hook_name: &str, timeout_secs: u64) { let sw = simple_stopwatch::Stopwatch::start_new(); @@ -235,6 +236,8 @@ where .creation_flags(CREATE_NO_WINDOW) .spawn()?; + let _ = unsafe { AllowSetForegroundWindow(cmd.id()) }; + fn check_process_status_and_output(status: std::process::ExitStatus, mut cmd: std::process::Child) -> Result { let mut stdout = cmd.stdout.take().unwrap(); let mut stderr = cmd.stderr.take().unwrap(); @@ -273,25 +276,8 @@ where S: AsRef, P: AsRef, { - Process::new(exe).args(args).current_dir(work_dir).spawn()?; - Ok(()) -} - -pub fn run_process_no_console(exe: S, args: Vec<&str>, work_dir: P) -> Result<()> -where - S: AsRef, - P: AsRef, -{ - Process::new(exe).args(args).current_dir(work_dir).creation_flags(CREATE_NO_WINDOW).spawn()?; - Ok(()) -} - -pub fn run_process_no_console_raw_args(exe: S, args: &str, work_dir: P) -> Result<()> -where - S: AsRef, - P: AsRef, -{ - Process::new(exe).raw_arg(args).current_dir(work_dir).creation_flags(CREATE_NO_WINDOW).spawn()?; + let cmd = Process::new(exe).args(args).current_dir(work_dir).spawn()?; + let _ = unsafe { AllowSetForegroundWindow(cmd.id()) }; Ok(()) } @@ -300,7 +286,8 @@ where S: AsRef, P: AsRef, { - Process::new(exe).raw_arg(args).current_dir(work_dir).spawn()?; + let cmd = Process::new(exe).raw_arg(args).current_dir(work_dir).spawn()?; + let _ = unsafe { AllowSetForegroundWindow(cmd.id()) }; Ok(()) } diff --git a/src/Velopack/UpdateExe.cs b/src/Velopack/UpdateExe.cs index 663d29c7..ed78edf1 100644 --- a/src/Velopack/UpdateExe.cs +++ b/src/Velopack/UpdateExe.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.InteropServices; using System.Threading; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -16,6 +17,10 @@ namespace Velopack /// public static class UpdateExe { + [DllImport("user32", SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + private static extern bool AllowSetForegroundWindow(int dwProcessId); + /// /// Runs Update.exe in the current working directory to apply updates, optionally restarting the application. /// @@ -62,6 +67,14 @@ namespace Velopack logger.Debug($"Restarting app to apply updates. Running: {psi.FileName} {debugArgs}"); var p = Process.Start(psi); + + try { + // this is an attempt to work around a bug where the restarted app fails to come to foreground. + AllowSetForegroundWindow(p.Id); + } catch (Exception ex) { + logger.LogWarning(ex, "Failed to allow Update.exe to set foreground window."); + } + Thread.Sleep(300); if (p == null) { throw new Exception("Failed to launch Update.exe process.");