Compare commits
2 Commits
e30a9629da
...
024d9b40e7
Author | SHA1 | Date | |
---|---|---|---|
024d9b40e7 | |||
baeeaf9305 |
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -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",
|
||||||
|
@ -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"] }
|
||||||
|
34
readme.md
34
readme.md
@ -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
|
||||||
|
```
|
||||||
|
103
src/config.rs
103
src/config.rs
@ -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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
32
src/win.rs
32
src/win.rs
@ -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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user