发送 Ctrl-C 以处理由 Java 打开的进程

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1835885/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 23:08:21  来源:igfitidea点击:

Send Ctrl-C to process open by Java

javawindows

提问by Nettogrof

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.

我通过 Runtime.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.

到目前为止,我尝试通过 Process 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 信号。我怎样才能做到这一点?

采纳答案by Brian Agnew

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 questionappears to be very similar and points to various resources of use.

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

回答by Kai

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 文件来完成这项工作。为此,我修改了 SendSingal.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.exe 并将其放在您启动 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...

PS:我很想在此处附加 SendSignalC.exe,但我认为不允许这样做。无论如何,如果您有一个正在运行的 cpp 编译器,这些更改将变得简单而直接...

回答by Huy Hóm H?nh

To terminate you can taskkilljavawith this code:

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

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

Hope this help!

希望这有帮助!

回答by user1079877

Switch to Java 9 and save your time, Processhas pidproperty now, check the documentation herefor details. You can easily kill another process like this:

切换到 Java 9 并节省您的时间,现在Processpid属性,请在此处查看文档以获取详细信息。您可以轻松杀死另一个进程,如下所示:

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