use std::ffi::OsStr;
use std::io;
#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt as _;
use std::path::Path;
use std::process::Command;
use std::process::Stdio;
use encoding::all::GBK;
use encoding::{DecoderTrap, Encoding};
pub const CREATE_NEW_CONSOLE: u32 = 0x00000010;
pub const CREATE_NO_WINDOW: u32 = 0x08000000;
pub fn cmd<I, S, P>(
exe: S,
args: I,
cwd: P,
has_window: bool,
autodecode: bool,
) -> io::Result<String>
where
I: IntoIterator<Item = S>,
S: AsRef<OsStr>,
P: AsRef<Path>,
{
let exe_full = cwd.as_ref().join(exe.as_ref());
let mut binding = Command::new(exe_full);
let cmd = binding
.args(args)
.current_dir(cwd)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped());
#[cfg(target_os = "windows")]
{
let flag = if has_window {
CREATE_NEW_CONSOLE
} else {
CREATE_NO_WINDOW
};
cmd.creation_flags(flag);
}
let output = cmd.output()?;
if !output.status.success() {
let stderr = String::from_utf8_lossy(&output.stderr);
Err(io::Error::new(io::ErrorKind::Other, stderr))
} else {
let stdout = output.stdout;
let _res = String::from_utf8(stdout.clone());
let res = if autodecode {
_res.unwrap_or(
GBK
.decode(&stdout, DecoderTrap::Strict)
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("GPK解码失败{}", e)))?,
)
} else {
_res.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?
};
Ok(res)
}
}