发送Ctrl-C以通过Java处理打开

时间:2009-12-02 21:16:04

标签: java windows

在Windows操作系统下。

我通过Runtime.getRuntime()启动一个子进程.exec(); 我想向进程发送一个“ctrl-c”来阻止它。

我做了一个小例子,使用Runtime.getRuntime()。exec(“ping google.com -n 100000”); 代码可以在那里找到:http://pastebin.com/f6315063f

到目前为止,我尝试通过Process outputStream发送char'3'(ctrl-C字符)。

以下是一些代码:

 cmd = re.exec("ping google.com -n 10000"); 
 out = new BufferedWriter (new OutputStreamWriter(cmd.getOutputStream()));
 input =  new BufferedReader (new  InputStreamReader(cmd.getInputStream()));


 char ctrlBreak = (char)3;
 //Different testing way to send the ctrlBreak;
 out.write(ctrlBreak);
 out.flush();
 out.write(ctrlBreak+"\n");
 out.flush();

我不想杀死进程,我只想发送一个Ctrl-C信号。 我怎么能这样做?

4 个答案:

答案 0 :(得分:8)

我相信Ctrl-C被shell捕获并转换为信号(SIGINT),该信号被发送到底层进程(在这种情况下是您生成的进程)。

所以我认为您需要获取进程ID,然后将相应的信号发送到该进程。 This question似乎非常相似,并指向各种使用资源。

答案 1 :(得分:5)

经过大量的试验,我找到了一个我现在喜欢的解决方案。 基本上,它的工作原理如下: 1.获取您启动的进程的进程ID 2.将此PID传递给稍微修改的SendSignal.exe版本,该版本发送Ctrl-C而不是Ctrl-Break

这两个步骤并非完全直截了当,但几乎都是如此。 对于1.您需要获得PID。 Java没有提供任何本机方式来获取它。 有很多主题讨论如何做到最好。 我决定你现在需要一个名字(参见下面代码中的getProcessIDs())。

对于2.您需要有一个工具将CTRL-C发送到给定的PID。同样,Java不会这样做。 有不同的方法(例如在python中使用包装器等),但所有这些方法都有些复杂。我发现最简单的方法是使用.exe-File来完成这项工作。为此,我修改了SendSingal.exe。您可以在此处获取源代码:1。然后,只需将所有出现的“BREAK”(也是小写字母)替换为“C”并重新编译。

将exe重命名为SendSignalC.exe并将其放在启动Java的子文件夹\ text \中。然后运行下面的代码并愉快地调用例如SendCTRLC.sendCtrlC( “howeveryourprogramiscall.exe”)。

/** 
 * Sends CTRL-C to running processes from Java (in Windows)
 * and ca get ProcessID(s) for a given process name.
 * IMPORTANT!
 * This function NEEDS SendSignalC.exe in the ext\ subdirectory.
 * @author Kai Goergen
 */

import java.io.*;
import java.util.*;

public class SendCTRLC() {


    /**
     * Get all PIDs for a given name and send CTRL-C to all
     * @param processName
     * @return
     */
    public static List<String> sendCTRLC(String processName) {
        // get all ProcessIDs for the processName
        List<String> processIDs = getProcessIDs(processName);
        System.out.println("" + processIDs.size() + " PIDs found for " + processName + ": " + processIDs.toString());
        for (String pid : processIDs) {
            // close it
            sendCTRLC(Integer.parseInt(pid));
        }
        return processIDs;
    }

    /**
     * Send CTRL-C to the process using a given PID
     * @param processID
     */
    public static void sendCTRLC(int processID) {
        System.out.println(" Sending CTRL+C to PID " + processID);
        try {
            Process p = Runtime.getRuntime().exec("cmd /c ext\\SendSignalC.exe " + processID);
            StreamGobbler.StreamGobblerLOGProcess(p);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * Get List of PIDs for a given process name
     * @param processName
     * @return
     */
    public static List<String> getProcessIDs(String processName) {
        List<String> processIDs = new ArrayList<String>();
        try {
            String line;
            Process p = Runtime.getRuntime().exec("tasklist /v /fo csv");
            BufferedReader input = new BufferedReader
                    (new InputStreamReader(p.getInputStream()));
            while ((line = input.readLine()) != null) {
                if (!line.trim().equals("")) {
                    // Pid is after the 1st ", thus it's argument 3 after splitting
                    String currentProcessName = line.split("\"")[1];
                    // Pid is after the 3rd ", thus it's argument 3 after splitting
                    String currentPID = line.split("\"")[3];
                    if (currentProcessName.equalsIgnoreCase(processName)) {
                        processIDs.add(currentPID);
                    }
                }
            }
            input.close();
        }
        catch (Exception err) {
            err.printStackTrace();
        }
        return processIDs;

    }
}
PS:我想在这里附上SendSignalC.exe,但我不认为我被允许。无论如何,如果你有一个正在运行的cpp编译器,那么改变很简单直接......

答案 2 :(得分:1)

切换到Java 9并节省您的时间,Process现在拥有pid属性,有关详细信息,请查看文档here。您可以轻松终止另一个进程,例如:

long pid = process.pid();
Runtime.getRuntime().exec("kill " + pid);

答案 3 :(得分:0)

要终止,您可以使用以下代码taskkill java

Runtime.getRuntime().exec("taskkill /f /im java.exe");

希望这有帮助!