在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信号。 我怎么能这样做?
答案 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");
希望这有帮助!