diff --git a/Cargo.toml b/Cargo.toml index f289654..7b3de94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,4 +19,4 @@ features = ["winuser", "wincon", "processthreadsapi"] [build-dependencies] winres = "0.1.0" -winapi = { version = "0.3", features = ["winnt"] } \ No newline at end of file +winapi = { version = "0.3", features = ["winnt"] } diff --git a/readme.md b/readme.md index aa8db2d..fe41534 100644 --- a/readme.md +++ b/readme.md @@ -1,3 +1,37 @@ # wrapper-rs 这是一个用 rust 写的, 最开始用于让 Nuitka 打包出来的东西也可以像 pyinstaller 一样能文件夹结构干净一些的小东西, 目前的计划是写成一个跨平台的玩意, 不过我先写完 Windows 版本再说 + +```text +call [选项] [--] [参数] +选项: + --hide 隐藏控制台窗口 (默认) + --show 显示控制台窗口 + --chdir=xxx 切换工作目录到 xxx + --bin=xxx 指定可执行文件 + --config=xxx 指定配置文件 + --help 输出这一堆东西(根据系统语言) + --help-zh 输出这一堆东西 + --help-en 输出这一堆东西(但是英文) +默认: + 隐藏控制台 + 切换工作目录到 ./lib + 运行 ./main +``` + +```text +call [options] [--] [arguments] +Options: + --hide Hide console window (default) + --show Show console window + --chdir=xxx Change working directory to xxx + --bin=xxx Specify executable file + --config=xxx Specify configuration file + --help Print this help message(based on system language) + --help-zh Print this help message(but in Chinese) + --help-en Print this help message +Defaults: + hide console + chdir ./lib + run ./main +``` diff --git a/src/config.rs b/src/config.rs index 525108f..97deb78 100644 --- a/src/config.rs +++ b/src/config.rs @@ -48,16 +48,20 @@ pub fn show_help() { Err(_) => { println!("{}", HELP_MESSAGE_ZH); } - } } +pub fn get_default_config() -> (bool, Option, String, String, String) { + let hard_default = (true, Some("lib".to_string()), "main".to_string(), "run.conf".to_string(), "".to_string()); + + hard_default +} + #[derive(Clone)] pub struct Config { pub show_console: bool, - pub chdir: Option, - pub bin: PathBuf, - pub config: Option, + pub chdir: Option, + pub bin: String, pub bin_arg: Vec, } @@ -68,7 +72,6 @@ impl Display for Config { s.push_str(&format!(" show_console: {}\n", self.show_console)); s.push_str(&format!(" chdir: {:?}\n", self.chdir)); s.push_str(&format!(" bin: {:?}\n", self.bin)); - s.push_str(&format!(" config: {:?}\n", self.config)); s.push_str(&format!(" bin_arg: {:?}\n", self.bin_arg)); s.push_str("}"); write!(f, "{}", s) @@ -78,37 +81,18 @@ impl Display for Config { impl Config { pub fn new( show_console: bool, - chdir: Option, - bin: PathBuf, - config: Option, + chdir: Option, + bin: String, bin_arg: Vec, ) -> Self { Config { show_console, chdir, bin, - config, bin_arg, } } - pub fn merge_from(&mut self, other: &Config) { - if other.show_console { - self.show_console = true; - } - if other.chdir.is_some() { - self.chdir = other.chdir.clone(); - } - if other.bin != PathBuf::from("./lib/main") { - self.bin = other.bin.clone(); - } - if other.config.is_some() { - self.config = other.config.clone(); - } - if !other.bin_arg.is_empty() { - self.bin_arg = other.bin_arg.clone(); - } - } - pub fn from_config(config_path: Option) -> Option { + pub fn from_config(config_path: Option) -> Option<(Option, Option, Option, Option)> { if config_path.is_none() { // 判断一下 ./run.conf 是否存在 let config_path = PathBuf::from("./run.conf"); @@ -156,22 +140,12 @@ impl Config { } } } - // 处理一下 bin - let bin = if let Some(bin) = bin { - PathBuf::from(bin) - } else { - PathBuf::from("./lib/main") - }; - let chdir = chdir.map(|x| PathBuf::from(x)); - let arg = if let Some(arg) = arg { - vec![arg] - } else { - Vec::new() - }; - Some(Self::new(show_console, chdir, bin, None, arg)) + Some((Some(show_console), chdir, bin, arg)) + } + pub fn from_cli() -> Option { - let mut show_console = false; + let mut show_console = None; let mut chdir: Option = None; let mut bin: Option = None; let mut config: Option = None; @@ -184,11 +158,11 @@ impl Config { } let index = args.iter().position(|x| x == "--"); - let bin_arg: Vec; + let bin_arg: Option>; if index.is_some() { - bin_arg = args[index.unwrap() + 1..].to_vec(); + bin_arg = Some(args[index.unwrap() + 1..].to_vec()); } else { - bin_arg = Vec::new(); + bin_arg = None; } // 先尝试获取指定的控制台参数 // --hide 表示隐藏控制台 @@ -202,9 +176,9 @@ impl Config { if args[i] == "--" { break; } else if args[i] == "--hide" { - show_console = false; + show_console = Some(false); } else if args[i] == "--show" { - show_console = true; + show_console = Some(true); } else if args[i].starts_with("--chdir=") { chdir = Some(args[i][8..].to_string()); } else if args[i].starts_with("--bin=") { @@ -213,24 +187,27 @@ impl Config { config = Some(PathBuf::from_str(&args[i][9..]).unwrap()); } } - // 处理一下 bin - let bin = if let Some(bin) = bin { - PathBuf::from(bin) + let default_conf: (bool, Option, String, String, String) = get_default_config(); + let conf_from_config: Option<(Option, Option, Option, Option)> = Self::from_config(config.clone()); + // 优先顺序: cli > config > default + if let Some(conf) = conf_from_config { + Some( + Self::new( + show_console.unwrap_or(conf.0.unwrap_or(default_conf.0)), + chdir.or(conf.1.or(default_conf.1)), + bin.unwrap_or(conf.2.unwrap_or(default_conf.2)), + bin_arg.unwrap_or(vec![conf.3.unwrap_or(default_conf.3)]), + ) + ) } else { - PathBuf::from("./main") - }; - // 默认为 chdir ./lib - let chdir = if let Some(chdir) = chdir { - Some(PathBuf::from(chdir)) - } else { - Some(PathBuf::from("./lib")) - }; - - let mut conf = Self::new(show_console, chdir, bin, config, bin_arg); - let conf_from_config = Self::from_config(conf.config.clone()); - if conf_from_config.is_some() { - conf.merge_from(&conf_from_config.unwrap()); + Some( + Self::new( + show_console.unwrap_or(default_conf.0), + chdir.or(default_conf.1), + bin.unwrap_or(default_conf.2), + bin_arg.unwrap_or(vec![default_conf.3]), + ) + ) } - Some(conf) } } diff --git a/src/main.rs b/src/main.rs index 4863c45..2149999 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,4 @@ -// #![windows_subsystem = "windows"] +#![windows_subsystem = "windows"] #[cfg(windows)] mod win; @@ -8,6 +8,7 @@ compile_error!("This program only support windows! (这个程序只支持windows mod config; pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); +pub const SHOW_CONSOLE: bool = false; fn main() { let config = config::Config::from_cli(); diff --git a/src/win.rs b/src/win.rs index 0f7f9c6..c7d2593 100644 --- a/src/win.rs +++ b/src/win.rs @@ -10,28 +10,19 @@ fn is_launched_from_console() -> bool { } let mut console_process_id: u32 = 0; winuser::GetWindowThreadProcessId(console_window, &mut console_process_id); - console_process_id != processthreadsapi::GetCurrentProcessId() } } -fn free_console() { +fn attach_console() { unsafe { - wincon::FreeConsole(); - } -} - -fn hide_window() { - unsafe { - let _hwnd = winuser::GetForegroundWindow(); - winuser::ShowWindow(_hwnd, winuser::SW_HIDE); - } -} - -fn show_window() { - unsafe { - let _hwnd = winuser::GetForegroundWindow(); - winuser::ShowWindow(_hwnd, winuser::SW_SHOW); + let _out = wincon::AttachConsole(wincon::ATTACH_PARENT_PROCESS); + if _out == 0 { + // GetLastError! + use std::io::Error; + let e = Error::last_os_error(); + println!("AttachConsole failed: {}", e); + } } } @@ -66,21 +57,22 @@ pub fn call_bin(config: &Config, started_from_console: bool) { .creation_flags(0x08000000_u32) .spawn() .expect("执行失败"); - free_console(); - hide_window(); child.wait().expect("等待失败"); } // 重新显示终端 (以防万一) - show_window(); } pub fn run(config: &Config) { + attach_console(); + println!("call {}", crate::VERSION); + println!("config: {}", config); // 先切换工作目录 if let Some(chdir) = config.chdir.as_ref() { std::env::set_current_dir(chdir).unwrap(); } // 检测一下是否是从控制台启动的 let started_from_console = is_launched_from_console(); + println!("started_from_console: {}", started_from_console); // 调用可执行文件 call_bin(&config, started_from_console); }