fix(windows): suppress console windows with FreeConsole, ShellExecuteW, and CREATE_NO_WINDOW
Some checks are pending
Release & Packaging / Build Linux Packages (.tar.gz, .deb, .rpm, .AppImage) (push) Waiting to run
Release & Packaging / Build Windows Binaries (.exe) (push) Waiting to run
Release & Packaging / Publish GitHub Release (push) Blocked by required conditions

This commit is contained in:
katR 2026-09-08 19:42:26 +05:30
parent 96dcfc1a17
commit 861c045a58
9 changed files with 119 additions and 46 deletions

2
Cargo.lock generated
View file

@ -3700,7 +3700,7 @@ dependencies = [
[[package]]
name = "scythe"
version = "0.2.8"
version = "0.2.9"
dependencies = [
"ashpd",
"cpal",

View file

@ -1,6 +1,6 @@
[package]
name = "scythe"
version = "0.2.8"
version = "0.2.9"
edition = "2024"
[[bin]]
@ -53,4 +53,6 @@ windows = { version = "0.58.0", features = [
"Win32_UI_Controls",
"Win32_System_Threading",
"Win32_System_LibraryLoader",
"Win32_System_Console",
"Win32_UI_Shell",
] }

View file

@ -27,11 +27,11 @@ RequestExecutionLevel user
Section "Scythe" SecMain
; Terminate any running instances so locked executables and DLLs can be updated cleanly
nsExec::Exec 'cmd.exe /C taskkill /F /IM scythe-ui.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM scythe-daemon.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM vrec-ui.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM vrec-daemon.exe /T >nul 2>&1'
nsExec::Exec 'powershell -NoProfile -NonInteractive -Command "Get-Process -Name scythe-ui, scythe-daemon, vrec-ui, vrec-daemon -ErrorAction SilentlyContinue | Stop-Process -Force"'
nsExec::Exec 'taskkill /F /IM scythe-ui.exe /T'
nsExec::Exec 'taskkill /F /IM scythe-daemon.exe /T'
nsExec::Exec 'taskkill /F /IM vrec-ui.exe /T'
nsExec::Exec 'taskkill /F /IM vrec-daemon.exe /T'
nsExec::Exec 'powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command "Get-Process -Name scythe-ui, scythe-daemon, vrec-ui, vrec-daemon -ErrorAction SilentlyContinue | Stop-Process -Force"'
Sleep 1500
SetOverwrite try
@ -52,11 +52,11 @@ Section "Scythe" SecMain
SectionEnd
Section "Uninstall"
nsExec::Exec 'cmd.exe /C taskkill /F /IM scythe-ui.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM scythe-daemon.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM vrec-ui.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM vrec-daemon.exe /T >nul 2>&1'
nsExec::Exec 'powershell -NoProfile -NonInteractive -Command "Get-Process -Name scythe-ui, scythe-daemon, vrec-ui, vrec-daemon -ErrorAction SilentlyContinue | Stop-Process -Force"'
nsExec::Exec 'taskkill /F /IM scythe-ui.exe /T'
nsExec::Exec 'taskkill /F /IM scythe-daemon.exe /T'
nsExec::Exec 'taskkill /F /IM vrec-ui.exe /T'
nsExec::Exec 'taskkill /F /IM vrec-daemon.exe /T'
nsExec::Exec 'powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command "Get-Process -Name scythe-ui, scythe-daemon, vrec-ui, vrec-daemon -ErrorAction SilentlyContinue | Stop-Process -Force"'
Sleep 1500
Delete "$DESKTOP\scythe.lnk"

View file

@ -9,11 +9,11 @@ RequestExecutionLevel user
Section
; Terminate any running instances so locked executables and DLLs can be updated cleanly
nsExec::Exec 'cmd.exe /C taskkill /F /IM scythe-ui.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM scythe-daemon.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM vrec-ui.exe /T >nul 2>&1'
nsExec::Exec 'cmd.exe /C taskkill /F /IM vrec-daemon.exe /T >nul 2>&1'
nsExec::Exec 'powershell -NoProfile -NonInteractive -Command "Get-Process -Name scythe-ui, scythe-daemon, vrec-ui, vrec-daemon -ErrorAction SilentlyContinue | Stop-Process -Force"'
nsExec::Exec 'taskkill /F /IM scythe-ui.exe /T'
nsExec::Exec 'taskkill /F /IM scythe-daemon.exe /T'
nsExec::Exec 'taskkill /F /IM vrec-ui.exe /T'
nsExec::Exec 'taskkill /F /IM vrec-daemon.exe /T'
nsExec::Exec 'powershell -NoProfile -NonInteractive -WindowStyle Hidden -Command "Get-Process -Name scythe-ui, scythe-daemon, vrec-ui, vrec-daemon -ErrorAction SilentlyContinue | Stop-Process -Force"'
Sleep 1500
SetOverwrite try

View file

@ -21,6 +21,12 @@ fn ensure_wayland_env() {
#[tokio::main]
#[allow(unused_assignments)]
async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
#[cfg(target_os = "windows")]
unsafe {
use windows::Win32::System::Console::FreeConsole;
let _ = FreeConsole();
}
ensure_wayland_env();
#[cfg(unix)]
@ -496,11 +502,16 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let _ = m.finalize();
}
if let Ok(exe) = std::env::current_exe() {
let _ = std::process::Command::new(exe)
.stdin(std::process::Stdio::null())
let mut cmd = std::process::Command::new(exe);
cmd.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn();
.stderr(std::process::Stdio::null());
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
cmd.creation_flags(0x08000000);
}
let _ = cmd.spawn();
}
std::thread::sleep(std::time::Duration::from_millis(150));
std::process::exit(0);

View file

@ -283,9 +283,19 @@ fn handle_save_replay() -> Result<(), Box<dyn std::error::Error + Send + Sync>>
}
fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let args: Vec<String> = env::args().collect();
#[cfg(target_os = "windows")]
unsafe {
let is_cli = args.iter().any(|a| a == "--status" || a == "--help" || a == "-h");
if !is_cli {
use windows::Win32::System::Console::FreeConsole;
let _ = FreeConsole();
}
}
ensure_wayland_env();
let args: Vec<String> = env::args().collect();
if args.len() > 1 {
match args[1].as_str() {
"--save" => {

View file

@ -51,13 +51,34 @@ pub fn spawn_toast(title: &str, subtitle: &str, icon: ToastIcon) {
let icon_owned = icon_str.to_string();
std::thread::spawn(move || {
let exe = std::env::current_exe().unwrap_or_else(|_| std::path::PathBuf::from("scythe-ui"));
let _ = std::process::Command::new(exe)
.args(["--toast", &title_owned, &subtitle_owned, &icon_owned])
let exe = if let Ok(mut p) = std::env::current_exe() {
p.pop();
#[cfg(target_os = "windows")]
let ui = p.join("scythe-ui.exe");
#[cfg(not(target_os = "windows"))]
let ui = p.join("scythe-ui");
if ui.exists() {
ui
} else {
std::env::current_exe().unwrap_or_else(|_| std::path::PathBuf::from("scythe-ui"))
}
} else {
std::path::PathBuf::from("scythe-ui")
};
let mut cmd = std::process::Command::new(&exe);
if let Some(parent) = exe.parent() {
cmd.current_dir(parent);
}
cmd.args(["--toast", &title_owned, &subtitle_owned, &icon_owned])
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::null())
.stderr(std::process::Stdio::null())
.spawn();
.stderr(std::process::Stdio::null());
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
cmd.creation_flags(0x08000000); // CREATE_NO_WINDOW
}
let _ = cmd.spawn();
});
}

View file

@ -48,14 +48,19 @@ fn format_egui_key(key: egui::Key) -> Option<String> {
}
fn probe_duration_sec(path: &std::path::Path) -> f32 {
let out = std::process::Command::new("ffprobe")
.args([
let mut cmd = std::process::Command::new("ffprobe");
cmd.args([
"-v", "error",
"-show_entries", "format=duration",
"-of", "default=noprint_wrappers=1:nokey=1",
])
.arg(path)
.output();
.arg(path);
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
cmd.creation_flags(0x08000000);
}
let out = cmd.output();
if let Ok(out) = out {
let text = String::from_utf8_lossy(&out.stdout);
if let Ok(val) = text.trim().parse::<f32>() {
@ -93,6 +98,11 @@ fn trim_clip(
"-avoid_negative_ts", "make_zero",
])
.arg(&out_path);
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
cmd.creation_flags(0x08000000);
}
let res = cmd.output().map_err(|e| format!("Failed to spawn ffmpeg: {}", e))?;
if res.status.success() {
@ -108,11 +118,21 @@ fn play_clip(path: &std::path::Path) {
std::thread::spawn(move || {
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
let _ = std::process::Command::new("cmd")
.args(["/C", "start", "", &p.to_string_lossy()])
.creation_flags(0x08000000)
.spawn();
use windows::core::HSTRING;
use windows::Win32::UI::Shell::ShellExecuteW;
use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
let path_str = p.to_string_lossy().to_string();
unsafe {
let _ = ShellExecuteW(
None,
windows::core::w!("open"),
&HSTRING::from(&path_str),
None,
None,
SW_SHOWNORMAL,
);
}
}
#[cfg(not(target_os = "windows"))]
{
@ -263,7 +283,7 @@ fn pick_folder(current_dir: &str, tx: Sender<String>, is_active: Arc<AtomicBool>
clean_cur, clean_cur
);
let mut cmd = std::process::Command::new("powershell.exe");
cmd.args(["-NoProfile", "-STA", "-Command", &script]);
cmd.args(["-NoProfile", "-NonInteractive", "-WindowStyle", "Hidden", "-STA", "-Command", &script]);
cmd.creation_flags(0x08000000);
if let Ok(out) = cmd.output() {
let sel = String::from_utf8_lossy(&out.stdout).trim().to_string();

View file

@ -123,11 +123,20 @@ pub fn open_browser_url(url: &str) {
std::thread::spawn(move || {
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
let _ = std::process::Command::new("cmd")
.args(["/C", "start", "", &u])
.creation_flags(0x08000000)
.spawn();
use windows::core::HSTRING;
use windows::Win32::UI::Shell::ShellExecuteW;
use windows::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL;
unsafe {
let _ = ShellExecuteW(
None,
windows::core::w!("open"),
&HSTRING::from(&u),
None,
None,
SW_SHOWNORMAL,
);
}
}
#[cfg(target_os = "macos")]
{