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
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).
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.
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").
/**
* 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...