Отправить Ctrl-C, чтобы открыть процесс с помощью Java - PullRequest
16 голосов
/ 03 декабря 2009

Под ОС Windows.

Я запускаю подпроцесс через Runtime.getRuntime (). Exec (); Я хочу отправить "ctrl-c" процессу, чтобы остановить его.

Я сделал небольшой пример с Runtime.getRuntime (). Exec ("ping google.com -n 100000"); Код можно найти там: http://pastebin.com/f6315063f

До сих пор я пытался отправить символ '3' (символ ctrl-C) через Process outputStream.

Вот немного кода:

 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. Как я могу это сделать?

Ответы [ 4 ]

8 голосов
/ 03 декабря 2009

Я полагаю, что Ctrl-C перехватывается оболочкой и переводится в сигнал ( SIGINT ), который отправляется базовому процессу (в данном случае вашему порожденному процессу).

Так что я думаю, вам нужно получить идентификатор процесса и затем отправить соответствующий сигнал этому процессу. Этот вопрос выглядит очень похожим и указывает на различные ресурсы использования.

5 голосов
/ 26 апреля 2012

После многих и многих испытаний я нашел решение, которое мне сейчас нравится. В основном это работает так: 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-компилятор ...

1 голос
/ 06 декабря 2018

Переключитесь на Java 9 и сэкономьте свое время, Process имеет свойство pid сейчас, проверьте документацию здесь для подробностей. Вы можете легко убить другой процесс, как этот:

long pid = process.pid();
Runtime.getRuntime().exec("kill " + pid);
0 голосов
/ 15 января 2016

Для завершения вы можете taskkill java с этим кодом:

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

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...