如何在Rust中杀死Windows上正在运行的子进程?

And*_*rew 2 process rust

我有一个在Windows上创建进程的函数。

pub fn create_process(url: String) {
    thread::spawn(move || {
        let _child = process::Command::new("cmd.exe")
            .arg("/C")
            .arg("ping")
            .arg(&url)
            .arg("-t")
            .spawn()
            .expect("Couldn't run 'ping'");
    });
}
Run Code Online (Sandbox Code Playgroud)

我有一个函数要终止(杀死)“ create_process()”创建的进程:

pub fn stop() {
    // ?????
}
Run Code Online (Sandbox Code Playgroud)

如何访问_child创建的create_process函数以终止其过程?还有其他方法可以终止该进程吗?

Art*_*mGr 5

TL; DR:使用kill方法。例如:

use std::process;
use std::thread;
use std::time::Duration;

fn main() {
    let mut child = process::Command::new("ping")
        .arg("8.8.8.8")
        .arg("-t")
        .spawn()
        .expect("Couldn't run 'ping'");

    thread::sleep(Duration::from_secs(5));
    child.kill().expect("!kill");
}
Run Code Online (Sandbox Code Playgroud)

注意,由于生成的进程已经与父进程并行,因此您不需要单独的线程。

在您的问题中,有一个使用“ cmd / C”运行“ ping”的代码示例。这产生的不是一个过程,而是两个过程:“ cmd”过程和“ ping”过程。杀死child会杀死“ cmd”进程,但可能会使“ ping”进程继续运行。

使用“ cmd / C”也是危险的,允许命令注入

如何访问函数中_child创建的内容create_process以终止其过程?

_child Send,这意味着你可以从线程发送到线程。跨线程发送数据的细节可能已经在许多相应的Stack Overflow问题中得到了介绍。

还有其他方法可以终止该进程吗?

您可以使用本机平台API。例如:

use std::process;
use std::thread;
use std::time::Duration;

fn main() {
    let mut child = process::Command::new("ping")
        .arg("8.8.8.8")
        .arg("-t")
        .spawn()
        .expect("Couldn't run 'ping'");

    thread::sleep(Duration::from_secs(5));
    child.kill().expect("!kill");
}
Run Code Online (Sandbox Code Playgroud)
#[macro_use]
extern crate gstuff;

use std::process;
use std::ptr::null_mut;
use std::thread;
use std::time::Duration;
use winapi::shared::minwindef::DWORD;
use winapi::shared::ntdef::HANDLE;
use winapi::um::processthreadsapi::{OpenProcess, TerminateProcess};
use winapi::um::winnt::{PROCESS_QUERY_INFORMATION, PROCESS_TERMINATE};

struct Process(HANDLE);
impl Process {
    fn open(pid: DWORD) -> Result<Process, String> {
        // https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320%28v=vs.85%29.aspx
        let pc = unsafe { OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_TERMINATE, 0, pid) };
        if pc == null_mut() {
            return ERR!("!OpenProcess");
        }
        Ok(Process(pc))
    }

    fn kill(self) -> Result<(), String> {
        unsafe { TerminateProcess(self.0, 1) };
        Ok(())
    }
}
impl Drop for Process {
    fn drop(&mut self) {
        unsafe { winapi::um::handleapi::CloseHandle(self.0) };
    }
}

fn main() {
    let child = process::Command::new("ping")
        .arg("8.8.8.8")
        .arg("-t")
        .spawn()
        .expect("Couldn't run 'ping'");

    let pid = child.id();
    let pc = Process::open(pid as DWORD).expect("!open");
    println!("Process {} opened.", pid);
    thread::sleep(Duration::from_secs(5));
    pc.kill().expect("!kill");
    println!("Process {} killed.", pid);
}
Run Code Online (Sandbox Code Playgroud)