2009-12-02 15 views
14

Unter Windows OS.Senden Ctrl-C zum Öffnen von Java öffnen

Ich starte einen Unterprozess über eine Runtime.getRuntime(). Exec(); Ich möchte eine "Strg-C" an den Prozess senden, um es zu stoppen.

Ich habe ein kleines Beispiel mit Runtime.getRuntime(). Exec ("ping google.com -n 100000"); Der Code kann dort gefunden werden: http://pastebin.com/f6315063f

Bisher habe ich versucht, die Char '3' (Ctrl-C-Zeichen) über Process OutputStream zu senden. Hier

ist ein Stück 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(); 

Ich will nicht, um den Prozess zu töten, ich will nur ein Ctrl-C-Signal senden. Wie kann ich das tun?

+0

Letztlich, was versuchst du zu erreichen? –

+0

Machen Sie einen Wrapper um ein altes DOS/Windows3.1/Win95 Anwendung – Nettogrof

+0

sollte es funktionieren, aber Sie sollten brechen nur einmal senden, es zweimal zu tun würde offensichtlich den Hauptprozess zu töten. –

Antwort

6

Ich glaube, Ctrl-C wird von der Shell abgefangen und in ein Signal (SIGINT) übersetzt, das an den zugrunde liegenden Prozess (in diesem Fall Ihren erzeugten Prozess) gesendet wird.

Also ich denke, Sie müssen die Prozess-ID erhalten und dann das entsprechende Signal an diesen Prozess senden. This question scheint sehr ähnlich zu sein und verweist auf verschiedene Ressourcen.

+0

Ich habe diese Frage gesehen, aber SendSignal sendet nur ein Ctrl-Break-Signal. – Nettogrof

+0

Also ich denke dann müssen Sie die Prozess-ID finden und senden Sie das SIGINT über (vielleicht) eine POSIX-Funktion oder ähnliches. –

5

Nach vielen und vielen Versuchen fand ich eine Lösung, die ich jetzt mag. Grundsätzlich funktioniert es wie folgt aus: 1. die Prozess-ID des Prozesses, die Sie 2. Pass diese PID auf eine leicht modifizierte Version von SendSignal.exe gestartet, die Ctrl-C anstelle von Ctrl-Break

sendet

Beide Schritte sind nicht ganz geradlinig, aber fast. Für 1. müssen Sie die PID erhalten. Java bietet keine native Möglichkeit, es zu bekommen. Es gibt eine Reihe von Threads, die darüber diskutieren, wie man das am besten macht. Ich entschied mich für einen, wo Sie jetzt den Namen benötigen (siehe getProcessIDs() im folgenden Code).

Für 2. benötigen Sie ein Werkzeug, das STRG-C an eine bestimmte PID sendet. Auch dies tut Java nicht. Es gibt verschiedene Möglichkeiten, dies zu tun (z. B. einen Wrapper in Python oder so), aber alle sind etwas kompliziert. Ich fand das einfachste ist, eine .exe-Datei zu verwenden, um die Aufgabe zu erledigen. Dazu habe ich SendSingal.exe modifiziert. Sie können den Quellcode hier bekommen: 1. Ersetzen Sie dann einfach alle Vorkommen von "BREAK" (auch in Kleinbuchstaben) durch "C" und kompilieren Sie neu.

Benennen Sie die Exe in SendSignalC.exe um und legen Sie sie in einen Unterordner ext \ von wo Sie Java starten. Führen Sie dann den folgenden Code aus und rufen Sie z. SendCTRLC.sendCtrlC ("howeyyourourprogramiscall.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: Ich würde SendSignalC.exe lieben hier zu befestigen, aber ich glaube nicht, dass ich erlaubt bin. Wie auch immer, sind die Änderungen einfach und unkompliziert, wenn Sie einen laufenden cpp-Compiler ...

+0

Das ist sehr interessant. Danke für das Teilen. – soulseekah

0

beenden Sie können taskkilljava mit diesem Code:

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

Hope this Hilfe!