Compare commits

...

2 Commits

Author SHA1 Message Date
024d9b40e7
bump 1.1.0 2024-01-23 00:51:22 +08:00
baeeaf9305
修复了不少小毛病 2024-01-23 00:50:35 +08:00
6 changed files with 91 additions and 87 deletions

2
Cargo.lock generated
View File

@ -4,7 +4,7 @@ version = 3
[[package]] [[package]]
name = "call" name = "call"
version = "1.0.0" version = "1.1.0"
dependencies = [ dependencies = [
"winapi", "winapi",
"winres", "winres",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "call" name = "call"
version = "1.0.0" version = "1.1.0"
description = "一个简单的用于不带控制台/带控制台调用其他程序的包装器" description = "一个简单的用于不带控制台/带控制台调用其他程序的包装器"
edition = "2021" edition = "2021"
build = "build.rs" build = "build.rs"
@ -19,4 +19,4 @@ features = ["winuser", "wincon", "processthreadsapi"]
[build-dependencies] [build-dependencies]
winres = "0.1.0" winres = "0.1.0"
winapi = { version = "0.3", features = ["winnt"] } winapi = { version = "0.3", features = ["winnt"] }

View File

@ -1,3 +1,37 @@
# wrapper-rs # wrapper-rs
这是一个用 rust 写的, 最开始用于让 Nuitka 打包出来的东西也可以像 pyinstaller 一样能文件夹结构干净一些的小东西, 目前的计划是写成一个跨平台的玩意, 不过我先写完 Windows 版本再说 这是一个用 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
```

View File

@ -48,16 +48,20 @@ pub fn show_help() {
Err(_) => { Err(_) => {
println!("{}", HELP_MESSAGE_ZH); println!("{}", HELP_MESSAGE_ZH);
} }
} }
} }
pub fn get_default_config() -> (bool, Option<String>, String, String, String) {
let hard_default = (true, Some("lib".to_string()), "main".to_string(), "run.conf".to_string(), "".to_string());
hard_default
}
#[derive(Clone)] #[derive(Clone)]
pub struct Config { pub struct Config {
pub show_console: bool, pub show_console: bool,
pub chdir: Option<PathBuf>, pub chdir: Option<String>,
pub bin: PathBuf, pub bin: String,
pub config: Option<PathBuf>,
pub bin_arg: Vec<String>, pub bin_arg: Vec<String>,
} }
@ -68,7 +72,6 @@ impl Display for Config {
s.push_str(&format!(" show_console: {}\n", self.show_console)); s.push_str(&format!(" show_console: {}\n", self.show_console));
s.push_str(&format!(" chdir: {:?}\n", self.chdir)); s.push_str(&format!(" chdir: {:?}\n", self.chdir));
s.push_str(&format!(" bin: {:?}\n", self.bin)); 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(&format!(" bin_arg: {:?}\n", self.bin_arg));
s.push_str("}"); s.push_str("}");
write!(f, "{}", s) write!(f, "{}", s)
@ -78,37 +81,18 @@ impl Display for Config {
impl Config { impl Config {
pub fn new( pub fn new(
show_console: bool, show_console: bool,
chdir: Option<PathBuf>, chdir: Option<String>,
bin: PathBuf, bin: String,
config: Option<PathBuf>,
bin_arg: Vec<String>, bin_arg: Vec<String>,
) -> Self { ) -> Self {
Config { Config {
show_console, show_console,
chdir, chdir,
bin, bin,
config,
bin_arg, bin_arg,
} }
} }
pub fn merge_from(&mut self, other: &Config) { pub fn from_config(config_path: Option<PathBuf>) -> Option<(Option<bool>, Option<String>, Option<String>, Option<String>)> {
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<PathBuf>) -> Option<Self> {
if config_path.is_none() { if config_path.is_none() {
// 判断一下 ./run.conf 是否存在 // 判断一下 ./run.conf 是否存在
let config_path = PathBuf::from("./run.conf"); let config_path = PathBuf::from("./run.conf");
@ -156,22 +140,12 @@ impl Config {
} }
} }
} }
// 处理一下 bin Some((Some(show_console), chdir, bin, arg))
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))
} }
pub fn from_cli() -> Option<Self> { pub fn from_cli() -> Option<Self> {
let mut show_console = false; let mut show_console = None;
let mut chdir: Option<String> = None; let mut chdir: Option<String> = None;
let mut bin: Option<String> = None; let mut bin: Option<String> = None;
let mut config: Option<PathBuf> = None; let mut config: Option<PathBuf> = None;
@ -184,11 +158,11 @@ impl Config {
} }
let index = args.iter().position(|x| x == "--"); let index = args.iter().position(|x| x == "--");
let bin_arg: Vec<String>; let bin_arg: Option<Vec<String>>;
if index.is_some() { if index.is_some() {
bin_arg = args[index.unwrap() + 1..].to_vec(); bin_arg = Some(args[index.unwrap() + 1..].to_vec());
} else { } else {
bin_arg = Vec::new(); bin_arg = None;
} }
// 先尝试获取指定的控制台参数 // 先尝试获取指定的控制台参数
// --hide 表示隐藏控制台 // --hide 表示隐藏控制台
@ -202,9 +176,9 @@ impl Config {
if args[i] == "--" { if args[i] == "--" {
break; break;
} else if args[i] == "--hide" { } else if args[i] == "--hide" {
show_console = false; show_console = Some(false);
} else if args[i] == "--show" { } else if args[i] == "--show" {
show_console = true; show_console = Some(true);
} else if args[i].starts_with("--chdir=") { } else if args[i].starts_with("--chdir=") {
chdir = Some(args[i][8..].to_string()); chdir = Some(args[i][8..].to_string());
} else if args[i].starts_with("--bin=") { } else if args[i].starts_with("--bin=") {
@ -213,24 +187,27 @@ impl Config {
config = Some(PathBuf::from_str(&args[i][9..]).unwrap()); config = Some(PathBuf::from_str(&args[i][9..]).unwrap());
} }
} }
// 处理一下 bin let default_conf: (bool, Option<String>, String, String, String) = get_default_config();
let bin = if let Some(bin) = bin { let conf_from_config: Option<(Option<bool>, Option<String>, Option<String>, Option<String>)> = Self::from_config(config.clone());
PathBuf::from(bin) // 优先顺序: 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 { } else {
PathBuf::from("./main") Some(
}; Self::new(
// 默认为 chdir ./lib show_console.unwrap_or(default_conf.0),
let chdir = if let Some(chdir) = chdir { chdir.or(default_conf.1),
Some(PathBuf::from(chdir)) bin.unwrap_or(default_conf.2),
} else { bin_arg.unwrap_or(vec![default_conf.3]),
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(conf)
} }
} }

View File

@ -1,4 +1,4 @@
// #![windows_subsystem = "windows"] #![windows_subsystem = "windows"]
#[cfg(windows)] #[cfg(windows)]
mod win; mod win;
@ -8,6 +8,7 @@ compile_error!("This program only support windows! (这个程序只支持windows
mod config; mod config;
pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
pub const SHOW_CONSOLE: bool = false;
fn main() { fn main() {
let config = config::Config::from_cli(); let config = config::Config::from_cli();

View File

@ -10,28 +10,19 @@ fn is_launched_from_console() -> bool {
} }
let mut console_process_id: u32 = 0; let mut console_process_id: u32 = 0;
winuser::GetWindowThreadProcessId(console_window, &mut console_process_id); winuser::GetWindowThreadProcessId(console_window, &mut console_process_id);
console_process_id != processthreadsapi::GetCurrentProcessId() console_process_id != processthreadsapi::GetCurrentProcessId()
} }
} }
fn free_console() { fn attach_console() {
unsafe { unsafe {
wincon::FreeConsole(); let _out = wincon::AttachConsole(wincon::ATTACH_PARENT_PROCESS);
} if _out == 0 {
} // GetLastError!
use std::io::Error;
fn hide_window() { let e = Error::last_os_error();
unsafe { println!("AttachConsole failed: {}", e);
let _hwnd = winuser::GetForegroundWindow(); }
winuser::ShowWindow(_hwnd, winuser::SW_HIDE);
}
}
fn show_window() {
unsafe {
let _hwnd = winuser::GetForegroundWindow();
winuser::ShowWindow(_hwnd, winuser::SW_SHOW);
} }
} }
@ -66,21 +57,22 @@ pub fn call_bin(config: &Config, started_from_console: bool) {
.creation_flags(0x08000000_u32) .creation_flags(0x08000000_u32)
.spawn() .spawn()
.expect("执行失败"); .expect("执行失败");
free_console();
hide_window();
child.wait().expect("等待失败"); child.wait().expect("等待失败");
} }
// 重新显示终端 (以防万一) // 重新显示终端 (以防万一)
show_window();
} }
pub fn run(config: &Config) { pub fn run(config: &Config) {
attach_console();
println!("call {}", crate::VERSION);
println!("config: {}", config);
// 先切换工作目录 // 先切换工作目录
if let Some(chdir) = config.chdir.as_ref() { if let Some(chdir) = config.chdir.as_ref() {
std::env::set_current_dir(chdir).unwrap(); std::env::set_current_dir(chdir).unwrap();
} }
// 检测一下是否是从控制台启动的 // 检测一下是否是从控制台启动的
let started_from_console = is_launched_from_console(); let started_from_console = is_launched_from_console();
println!("started_from_console: {}", started_from_console);
// 调用可执行文件 // 调用可执行文件
call_bin(&config, started_from_console); call_bin(&config, started_from_console);
} }