当命令包含空格时,cmd /C 在 Rust 中不起作用

cmd /C doesn't work in Rust when command includes spaces

我想从 Rust 程序运行这个命令:

"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" "https://whosebug.com/"

在 cmd 中,这有效。

cmd /C ""C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" "https://whosebug.com/""

在 C# 中,这有效。

var comm = @"""""C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"" ""https://whosebug.com/""""";
System.Diagnostics.Process.Start("cmd", "/C " + comm);

在 Rust 中,这不起作用。

let comm = r#"""C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" "https://whosebug.com/"""#;
let output = Command::new("cmd")
    .args(&["/C", comm])
    .output()
    .expect("failed to execute process");

我收到以下错误。

The network path was not found.

但是,当 commecho hello 时有效。

我尝试了另外两种方法:

  1. 这个

    let comm = r#"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe https://whosebug.com/"#;
    

    'C:\Program' is not recognized as an internal or external command,
    operable program or batch file.
    
  2. 这个

    let comm = r#""C:\Program Files (x86)\Google\Chrome\Application\chrome.exe https://whosebug.com/""#;
    

    '\"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe\"' is not recognized as an internal or external command,
    operable program or batch file.
    

这是a known issue。不幸的是,转义参数的 Windows 规则非常重要且难以正确执行。

此代码:

let comm = r#""C:\Program Files\Google\Chrome\Application\chrome.exe" https://whosebug.com/"#;
let mut cmd = Command::new("cmd");
cmd.arg("/c");
cmd.arg(comm);

执行这个:

"cmd" "/c" "\"C:\Program Files\Google\Chrome\Application\chrome.exe\" https://whosebug.com/"

不幸的是,内引号被转义了,尽管在这种情况下它们不应该被转义。


作为变通方法,在许多情况下,您实际上不需要使用 cmd。在这些情况下,直接执行流程更为明智:

let output = Command::new(r#"C:\Program Files\Google\Chrome\Application\chrome.exe"#)
    .args(&["https://whosebug.com/"])
    .output()
    .expect("failed to execute process");

我找到了类似情况的解决方案:

use std::process::Command;
use std::thread;
use std::time;

fn main() {
    let child = Command::new("netsh")
        .arg("advfirewall")
        .arg("firewall")
        .arg("add")
        .arg("rule")
        .arg(r#"name="something2""#)
        .arg("dir=in")
        .arg("action=allow")
        .arg("protocol=TCP")
        .arg("localport=12006")
        .spawn()
        .expect("failed");
    thread::sleep(time::Duration::new(10, 0));
    println!("done");
    let output = child.stdout;
    println!("{:?}", output);
}

这处理命令行提示

netsh advfirewall firewall add rule name="something2" dir=in action=allow protocol=TCP localport=12006