cyfs_util/util/
process_util.rs

1use std::process::Command;
2
3pub struct ProcessUtil;
4
5impl ProcessUtil {
6    // 解析命令行,支持带空格的路径和参数
7    // 参数可以使用单引号和双引号前后包括(前后必须相同,都为单引号或者都为双引号),
8    // 避免内部含有空格和引号被分割为多个参数
9    pub fn parse_cmd(cmd: &str) -> Vec<&str> {
10        let mut args = Vec::new();
11        let mut next_quot: Option<char> = None;
12        let mut prev_index = 0;
13        for (i, c) in cmd.chars().enumerate() {
14            if c == '"' || c == '\'' {
15                if next_quot.is_none() {
16                    next_quot = Some(c);
17                } else if *next_quot.as_ref().unwrap() != c {
18                    continue;
19                } else {
20                    next_quot = None;
21
22                    let arg = &cmd[prev_index..(i + 1)];
23                    let arg = arg.trim_start_matches(c).trim_end_matches(c);
24                    if !arg.is_empty() {
25                        args.push(arg);
26                    }
27
28                    prev_index = i + 1;
29                }
30            } else if c.is_whitespace() && next_quot.is_none() {
31                let arg = &cmd[prev_index..(i + 1)];
32                let arg = arg.trim_start().trim_end();
33                if !arg.is_empty() {
34                    args.push(arg);
35                }
36
37                prev_index = i + 1;
38            }
39        }
40
41        // 如果存在最后一段,那么加入
42        if prev_index < cmd.len() {
43            let arg = &cmd[prev_index..cmd.len()];
44            let arg = arg.trim_start().trim_end();
45            if !arg.is_empty() {
46                args.push(arg);
47            }
48        }
49        args
50    }
51
52    // windows平台默认不detach,如果设定了detach,要特殊处理
53    #[cfg(target_os = "windows")]
54    pub fn detach(cmd: &mut Command) {
55        use std::os::windows::process::CommandExt;
56
57        pub const DETACHED_PROCESS: u32 = 0x00000008;
58        pub const CREATE_NEW_PROCESS_GROUP: u32 = 0x00000200;
59        pub const CREATE_NO_WINDOW: u32 = 0x08000000;
60
61        let flags = DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW;
62        cmd.creation_flags(flags);
63    }
64
65    #[cfg(not(target_os = "windows"))]
66    pub fn detach(_cmd: &mut Command) {}
67}
68
69// #[cfg(test)]
70// mod tests {
71//     use super::ProcessUtil;
72
73//     #[test]
74//     fn test_parse_cmd() {
75//         let v = r#""C:\\www www" yyyy 'asd" asd'  'name xxx' --status"#;
76//         let ret = ProcessUtil::parse_cmd(v);
77//         assert_eq!(ret.len(), 5);
78//         assert_eq!(ret[0], r#"C:\\www www"#);
79//         assert_eq!(ret[1], r#"yyyy"#);
80//         assert_eq!(ret[2], r#"asd" asd"#);
81//         assert_eq!(ret[3], r#"name xxx"#);
82//         assert_eq!(ret[3], r#"--status"#);
83
84//         println!("{:?}", ret);
85//     }
86// }