После многих и многих испытаний я нашел решение, которое мне сейчас нравится.
В основном это работает так:
1. Получите идентификатор процесса, который вы начали
2. Передайте этот PID в слегка измененную версию SendSignal.exe, которая отправляет Ctrl-C вместо Ctrl-Break
Оба шага не совсем прямые, но почти.
Для 1. вам нужно получить PID. Java не предоставляет никакого собственного способа получить его.
Есть несколько тем, обсуждающих, как сделать это лучше всего.
Я решил, что вам нужно указать имя (см. GetProcessIDs () в приведенном ниже коде).
Для 2. вам нужно иметь инструмент, который отправляет CTRL-C на заданный PID. Опять же, Java не делает этого.
Есть разные способы сделать это (например, использовать обертку в Python или около того), но все они несколько сложны. Я обнаружил, что проще всего использовать файл .exe для выполнения этой работы. Для этого я модифицировал SendSingal.exe. Вы можете получить исходный код здесь: 1. Затем просто замените все вхождения «BREAK» (также строчными буквами) на «C» и перекомпилируйте.
Переименуйте исполняемый файл в SendSignalC.exe и поместите его в подпапку ext \, где вы запускаете Java. Затем запустите приведенный ниже код и с радостью позвоните, например, 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-компилятор ...