1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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());
// 设置 CREATE_NO_WINDOW 标志
  #[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)
  }
}