pub const CREATE_NO_WINDOW: u32 = 0x0800_0000;
pub const DETACHED_PROCESS: u32 = 0x0000_0008;
pub const CREATE_NEW_PROCESS_GROUP: u32 = 0x0000_0200;
pub const HEADLESS_SPAWN_FLAGS: u32 = CREATE_NO_WINDOW | DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
pub fn hide_console(command: &mut std::process::Command) {
set_creation_flags(command, CREATE_NO_WINDOW);
}
pub fn hide_console_tokio(command: &mut tokio::process::Command) {
#[cfg(windows)]
{
hide_console(command.as_std_mut());
}
#[cfg(not(windows))]
{
let _ = command;
}
}
pub fn set_creation_flags(command: &mut std::process::Command, flags: u32) {
#[cfg(windows)]
{
use std::os::windows::process::CommandExt;
command.creation_flags(flags);
}
#[cfg(not(windows))]
{
let _ = (command, flags);
}
}
pub fn hide_console_detached(command: &mut std::process::Command) {
set_creation_flags(command, HEADLESS_SPAWN_FLAGS);
}
pub fn free_console() {
#[cfg(windows)]
{
unsafe {
let _ = windows_sys::Win32::System::Console::FreeConsole();
}
}
}
pub fn ignore_console_close_events() {
#[cfg(windows)]
{
unsafe extern "system" fn handler(ctrl: u32) -> i32 {
use windows_sys::Win32::System::Console::{
CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, CTRL_SHUTDOWN_EVENT,
};
match ctrl {
CTRL_CLOSE_EVENT | CTRL_LOGOFF_EVENT | CTRL_SHUTDOWN_EVENT => 1, _ => 0,
}
}
unsafe {
let _ = windows_sys::Win32::System::Console::SetConsoleCtrlHandler(Some(handler), 1);
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hide_console_keeps_program_and_args() {
let mut c = std::process::Command::new("prog");
c.arg("a").arg("b");
hide_console(&mut c);
assert_eq!(c.get_program(), std::ffi::OsStr::new("prog"));
assert_eq!(c.get_args().collect::<Vec<_>>(), ["a", "b"]);
}
#[test]
fn create_no_window_constant() {
assert_eq!(CREATE_NO_WINDOW, 0x0800_0000);
assert_eq!(DETACHED_PROCESS, 0x0000_0008);
assert_ne!(HEADLESS_SPAWN_FLAGS & CREATE_NO_WINDOW, 0);
}
}