将Ctrl-C发送到Java打开的进程

时间:2022-07-27 04:00:19

Under Windows OS.

在Windows操作系统。

I start a sub-process via a Runtime.getRuntime().exec(); I want to send a "ctrl-c" to the process to stop it.

我通过运行时. getruntime ().exec()启动子进程;我想向进程发送一个“ctrl-c”来停止它。

I did a small example, with Runtime.getRuntime().exec("ping google.com -n 100000"); The code can be found there : http://pastebin.com/f6315063f

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

So far, I tried to send the char '3' (ctrl-C character) via Process outputStream.

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

Here is a bit of code:

这里有一些代码:

 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();

I don't want to kill the process, I just want to send a Ctrl-C signal. How can I do that?

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

3 个解决方案

#1


6  

I believe Ctrl-C is caught by the shell and translated into a signal (SIGINT) which is sent to the underlying process (in this case your spawned process).

我认为Ctrl-C被shell捕获并转换为一个信号(SIGINT),它被发送到底层进程(在本例中是衍生进程)。

So I think you'll need to get the process id and then send the appropriate signal to that process. This question appears to be very similar and points to various resources of use.

因此,我认为您需要获得进程id,然后向该进程发送适当的信号。这个问题似乎非常相似,并指向各种使用资源。

#2


5  

After lots and lots of trials, I found a solution that I like now. Basically, it works like this: 1. Get the Process ID of the process that you started 2. Pass this PID to a slightly modified version of SendSignal.exe, which sends Ctrl-C instead of Ctrl-Break

经过无数次的尝试,我找到了一个我现在喜欢的解决方案。基本上,它是这样工作的:1。获取启动的进程的进程ID 2。将这个PID传递给稍微修改过的SendSignal。exe,它发送Ctrl-C而不是Ctrl-Break

Both steps are not completely straight forward, but nearly. For 1. you need to get the PID. Java does not provide any native way to get it. There are a number of threads discussing about how to do that best. I decided for one where you need to now the name (see getProcessIDs() in the code below).

这两个步骤并不是完全直截了当的,但差不多。为1。你需要得到PID。Java没有提供任何本机方法来获取它。有许多线程正在讨论如何做到最好。我选择了一个您现在需要的名称(参见下面代码中的getProcessIDs()))。

For 2. you need to have a tool that sends CTRL-C to a given PID. Again, Java does not do this. There are different ways to do it (e.g. using a wrapper in python or so), but all of them are somewhat complicated. I found the easiest one is to use a .exe-File to do the job. For this, I modified SendSingal.exe. You can get the sourcecode here: 1. Then, simply replace all occurences of "BREAK" (also in lowercase letters) by "C" and recompile.

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

Rename the exe to SendSignalC.exe and put it in a subfolder ext\ of where you start Java. Then run the code below and happily call e.g. SendCTRLC.sendCtrlC("howeveryourprogramiscall.exe").

将exe重命名为SendSignalC。将它放在启动Java的子文件夹ext\中。然后运行下面的代码,并愉快地调用例如: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: I would love to attach SendSignalC.exe here, but I don't think that I'm allowed to. Anyhow, the changes are simple and straight-forward if you have a running cpp-compiler...

附注:我想附上SendSignalC。但是我不认为我可以。无论如何,如果您有一个正在运行的cpp编译器,这些更改是简单而直接的……

#3


0  

To terminate you can taskkill java with this code:

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

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

Hope this help!

希望这次的帮助!

#1


6  

I believe Ctrl-C is caught by the shell and translated into a signal (SIGINT) which is sent to the underlying process (in this case your spawned process).

我认为Ctrl-C被shell捕获并转换为一个信号(SIGINT),它被发送到底层进程(在本例中是衍生进程)。

So I think you'll need to get the process id and then send the appropriate signal to that process. This question appears to be very similar and points to various resources of use.

因此,我认为您需要获得进程id,然后向该进程发送适当的信号。这个问题似乎非常相似,并指向各种使用资源。

#2


5  

After lots and lots of trials, I found a solution that I like now. Basically, it works like this: 1. Get the Process ID of the process that you started 2. Pass this PID to a slightly modified version of SendSignal.exe, which sends Ctrl-C instead of Ctrl-Break

经过无数次的尝试,我找到了一个我现在喜欢的解决方案。基本上,它是这样工作的:1。获取启动的进程的进程ID 2。将这个PID传递给稍微修改过的SendSignal。exe,它发送Ctrl-C而不是Ctrl-Break

Both steps are not completely straight forward, but nearly. For 1. you need to get the PID. Java does not provide any native way to get it. There are a number of threads discussing about how to do that best. I decided for one where you need to now the name (see getProcessIDs() in the code below).

这两个步骤并不是完全直截了当的,但差不多。为1。你需要得到PID。Java没有提供任何本机方法来获取它。有许多线程正在讨论如何做到最好。我选择了一个您现在需要的名称(参见下面代码中的getProcessIDs()))。

For 2. you need to have a tool that sends CTRL-C to a given PID. Again, Java does not do this. There are different ways to do it (e.g. using a wrapper in python or so), but all of them are somewhat complicated. I found the easiest one is to use a .exe-File to do the job. For this, I modified SendSingal.exe. You can get the sourcecode here: 1. Then, simply replace all occurences of "BREAK" (also in lowercase letters) by "C" and recompile.

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

Rename the exe to SendSignalC.exe and put it in a subfolder ext\ of where you start Java. Then run the code below and happily call e.g. SendCTRLC.sendCtrlC("howeveryourprogramiscall.exe").

将exe重命名为SendSignalC。将它放在启动Java的子文件夹ext\中。然后运行下面的代码,并愉快地调用例如: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: I would love to attach SendSignalC.exe here, but I don't think that I'm allowed to. Anyhow, the changes are simple and straight-forward if you have a running cpp-compiler...

附注:我想附上SendSignalC。但是我不认为我可以。无论如何,如果您有一个正在运行的cpp编译器,这些更改是简单而直接的……

#3


0  

To terminate you can taskkill java with this code:

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

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

Hope this help!

希望这次的帮助!