2009-12-02 22 views
14

En el sistema operativo Windows.Enviar Ctrl-C al proceso abierto por Java

Comienzo un subproceso a través de Runtime.getRuntime(). Exec(); Deseo enviar un "ctrl-c" al proceso para detenerlo.

Hice un pequeño ejemplo, con Runtime.getRuntime(). Exec ("ping google.com -n 100000"); El código se puede encontrar allí: http://pastebin.com/f6315063f

Hasta ahora, traté de enviar el carácter "3" (carácter ctrl-C) a través del proceso outputStream.

Aquí es un poco de código:

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(); 

No quiero matar el proceso, sólo quiero enviar una señal Ctrl-C. ¿Cómo puedo hacer eso?

+0

En última instancia, ¿qué estás tratando de lograr? –

+0

Haz un contenedor alrededor de un viejo DOS/windows3.La aplicación 1/win95 – Nettogrof

+0

debería funcionar pero deberías enviar un corte solo una vez, hacerlo dos veces obviamente mataría el proceso principal. –

Respuesta

6

Creo que Ctrl-C es capturado por el shell y traducido a una señal (SIGINT) que se envía al proceso subyacente (en este caso, el proceso generado).

Así que creo que necesitarás obtener la identificación del proceso y luego enviar la señal adecuada a ese proceso. This question parece ser muy similar y apunta a varios recursos de uso.

+0

Vi esa pregunta, pero SendSignal envió solo una señal de ctrl-break. – Nettogrof

+0

Entonces, creo que necesita encontrar el ID del proceso y enviar el SIGINT a través de (tal vez) una función POSIX o similar. –

5

Después de muchas pruebas, encontré una solución que me gusta ahora. Básicamente, funciona así: 1. obtener el ID de proceso del proceso que inició 2. Pasar este PID a una versión ligeramente modificada de SendSignal.exe, que envía Ctrl-C en lugar de Ctrl-Break

Ambos pasos no son completamente sencillos, pero casi. Para 1. necesita obtener el PID. Java no proporciona ninguna forma nativa para obtenerlo. Hay una serie de discusiones discutiendo sobre cómo hacer eso mejor. Decidí por una en la que necesita ahora el nombre (vea getProcessIDs() en el código a continuación).

Para 2. usted necesita tener una herramienta que envíe CTRL-C a un PID dado. Nuevamente, Java no hace esto. Existen diferentes formas de hacerlo (por ejemplo, utilizar un contenedor en python), pero todas son algo complicadas. Encontré el más fácil es usar un archivo .exe para hacer el trabajo. Para esto, modifiqué SendSingal.exe. Puede obtener el código fuente aquí: 1. Luego, simplemente reemplace todas las ocurrencias de "BREAK" (también en letras minúsculas) por "C" y vuelva a compilar.

Cambie el nombre del exe a SendSignalC.exe y colóquelo en una subcarpeta ext \ donde inicia Java. A continuación, ejecute el siguiente código y felizmente llame, p. 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; 

    } 
} 

PD: Me gustaría conectar SendSignalC.exe aquí, pero no creo que se me permite. De todos modos, los cambios son simples y directo si tiene un compilador de CPP-correr ...

+0

Esto es muy interesante. Gracias por compartir. – soulseekah

0

Para terminar se puede taskkilljava con este código:

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

Esperanza esta ayuda!

Cuestiones relacionadas