207 lines
6.1 KiB
Rust
207 lines
6.1 KiB
Rust
/**
|
|
* Command utilities for hiding console windows in production builds
|
|
*
|
|
* This module provides utilities to configure std::process::Command instances
|
|
* to hide console windows on Windows in production builds, preventing the
|
|
* flash of command prompt windows when executing external processes.
|
|
*/
|
|
|
|
use std::process::Command;
|
|
|
|
// Windows-specific imports for hiding console window
|
|
#[cfg(target_os = "windows")]
|
|
use std::os::windows::process::CommandExt;
|
|
|
|
// Windows process creation flags
|
|
#[cfg(target_os = "windows")]
|
|
const CREATE_NO_WINDOW: u32 = 0x08000000;
|
|
|
|
/// Configure a Command to hide console window in production builds on Windows
|
|
///
|
|
/// This function applies the CREATE_NO_WINDOW flag to prevent console window
|
|
/// flashing when spawning processes from a GUI application. The console window
|
|
/// is only hidden in release builds to preserve debugging capabilities during
|
|
/// development.
|
|
///
|
|
/// # Arguments
|
|
/// * `cmd` - Mutable reference to the Command to configure
|
|
///
|
|
/// # Example
|
|
/// ```rust
|
|
/// use std::process::Command;
|
|
/// use crate::command_utils::configure_no_window;
|
|
///
|
|
/// let mut cmd = Command::new("python");
|
|
/// configure_no_window(&mut cmd);
|
|
/// let output = cmd.output();
|
|
/// ```
|
|
pub fn configure_no_window(cmd: &mut Command) {
|
|
#[cfg(target_os = "windows")]
|
|
{
|
|
// Only hide console window in release builds
|
|
// In debug builds, keep console visible for debugging
|
|
#[cfg(not(debug_assertions))]
|
|
{
|
|
cmd.creation_flags(CREATE_NO_WINDOW);
|
|
println!("Console window hidden for release build");
|
|
}
|
|
|
|
#[cfg(debug_assertions)]
|
|
{
|
|
println!("Console window visible for debug build");
|
|
}
|
|
}
|
|
|
|
// On non-Windows platforms, this function does nothing
|
|
#[cfg(not(target_os = "windows"))]
|
|
{
|
|
// No-op on non-Windows platforms
|
|
let _ = cmd; // Suppress unused variable warning
|
|
}
|
|
}
|
|
|
|
/// Create a new Command with console window hiding configured
|
|
///
|
|
/// This is a convenience function that creates a new Command and immediately
|
|
/// configures it to hide console windows in production builds.
|
|
///
|
|
/// # Arguments
|
|
/// * `program` - The program to execute
|
|
///
|
|
/// # Returns
|
|
/// A configured Command instance
|
|
///
|
|
/// # Example
|
|
/// ```rust
|
|
/// use crate::command_utils::create_hidden_command;
|
|
///
|
|
/// let mut cmd = create_hidden_command("python");
|
|
/// cmd.args(&["-c", "print('Hello, World!')"]);
|
|
/// let output = cmd.output();
|
|
/// ```
|
|
pub fn create_hidden_command<S: AsRef<std::ffi::OsStr>>(program: S) -> Command {
|
|
let mut cmd = Command::new(program);
|
|
configure_no_window(&mut cmd);
|
|
cmd
|
|
}
|
|
|
|
/// Configure a Command for Python execution with console window hiding
|
|
///
|
|
/// This function configures a Command specifically for Python execution,
|
|
/// including proper encoding setup and console window hiding.
|
|
///
|
|
/// # Arguments
|
|
/// * `cmd` - Mutable reference to the Command to configure
|
|
/// * `project_root` - The working directory for the command
|
|
/// * `args` - Command line arguments
|
|
///
|
|
/// # Example
|
|
/// ```rust
|
|
/// use std::process::Command;
|
|
/// use std::path::Path;
|
|
/// use crate::command_utils::configure_python_command;
|
|
///
|
|
/// let mut cmd = Command::new("python");
|
|
/// let args = vec!["-c".to_string(), "print('Hello')".to_string()];
|
|
/// configure_python_command(&mut cmd, Path::new("."), &args);
|
|
/// ```
|
|
pub fn configure_python_command(cmd: &mut Command, project_root: &std::path::Path, args: &[String]) {
|
|
cmd.current_dir(project_root);
|
|
cmd.args(args);
|
|
cmd.stdout(std::process::Stdio::piped());
|
|
cmd.stderr(std::process::Stdio::piped());
|
|
|
|
// Set environment variables for consistent encoding
|
|
cmd.env("PYTHONIOENCODING", "utf-8");
|
|
cmd.env("PYTHONUNBUFFERED", "1");
|
|
|
|
// Platform-specific configurations
|
|
if cfg!(target_os = "windows") {
|
|
cmd.env("PYTHONUTF8", "1");
|
|
}
|
|
|
|
// Configure console window hiding
|
|
configure_no_window(cmd);
|
|
}
|
|
|
|
/// Configure a Command for system operations (file/folder opening)
|
|
///
|
|
/// This function configures a Command for system operations like opening
|
|
/// files or folders, with appropriate console window hiding.
|
|
///
|
|
/// # Arguments
|
|
/// * `cmd` - Mutable reference to the Command to configure
|
|
///
|
|
/// # Example
|
|
/// ```rust
|
|
/// use std::process::Command;
|
|
/// use crate::command_utils::configure_system_command;
|
|
///
|
|
/// let mut cmd = Command::new("explorer");
|
|
/// cmd.arg("C:\\");
|
|
/// configure_system_command(&mut cmd);
|
|
/// ```
|
|
pub fn configure_system_command(cmd: &mut Command) {
|
|
// Configure console window hiding for system commands
|
|
configure_no_window(cmd);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use std::process::Command;
|
|
|
|
#[test]
|
|
fn test_configure_no_window() {
|
|
let mut cmd = Command::new("echo");
|
|
configure_no_window(&mut cmd);
|
|
// Test should not panic
|
|
}
|
|
|
|
#[test]
|
|
fn test_create_hidden_command() {
|
|
let cmd = create_hidden_command("echo");
|
|
// Test should not panic and should return a Command
|
|
assert_eq!(cmd.get_program(), "echo");
|
|
}
|
|
|
|
#[test]
|
|
fn test_configure_python_command() {
|
|
let mut cmd = Command::new("python");
|
|
let args = vec!["-c".to_string(), "print('test')".to_string()];
|
|
configure_python_command(&mut cmd, std::path::Path::new("."), &args);
|
|
// Test should not panic
|
|
}
|
|
|
|
#[test]
|
|
fn test_configure_system_command() {
|
|
let mut cmd = Command::new("echo");
|
|
configure_system_command(&mut cmd);
|
|
// Test should not panic
|
|
}
|
|
}
|
|
|
|
/// Utility macro for creating a hidden command with arguments
|
|
///
|
|
/// This macro provides a convenient way to create and configure a Command
|
|
/// with console window hiding in a single expression.
|
|
///
|
|
/// # Example
|
|
/// ```rust
|
|
/// use crate::command_utils::hidden_command;
|
|
///
|
|
/// let output = hidden_command!("python", "-c", "print('Hello')").output();
|
|
/// ```
|
|
#[macro_export]
|
|
macro_rules! hidden_command {
|
|
($program:expr $(, $arg:expr)*) => {
|
|
{
|
|
let mut cmd = $crate::command_utils::create_hidden_command($program);
|
|
$(cmd.arg($arg);)*
|
|
cmd
|
|
}
|
|
};
|
|
}
|
|
|
|
// Note: The hidden_command macro is automatically available when this module is imported
|