2009-12-02 10 views
14

Windows OSの場合。Javaで処理するCtrl-Cを送信

Runtime.getRuntime()。exec();を使用してサブプロセスを開始します。 "ctrl-c"をプロセスに送信して停止したいとします。

私は、Runtime.getRuntime()。exec( "ping google.com -n 100000")を使用して小さな例を作成しました。 コードはそこに見つけることができます:http://pastebin.com/f6315063f

これまで、私はプロセスのoutputStream経由でchar '3'(ctrl-C文字)を送信しようとしました。ここで

は、コードのビットは次のとおりです。

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信号を送信したい、プロセスを強制終了する必要はありません。 どうすればいいですか?

+0

最終的には、何を達成しようとしていますか? –

+0

古いDOS/windows3の周りにラッパーを行います。1/win95アプリケーション – Nettogrof

+0

が動作するはずですが、ブレークは一度だけ送信してください。二度実行すると明らかにメインプロセスが終了します。 –

答えて

6

私はCtrl-Cがシェルによってキャッチされ、基礎となるプロセス(この場合はあなたのスポーンされたプロセス)に送信される信号(SIGINT)に変換されると考えています。

だから、あなたはプロセスIDを取得し、そのプロセスに適切な信号を送る必要があると思います。 This questionは非常によく似ており、さまざまな使用リソースを指しています。

+0

私はその質問を見ましたが、SendSignalはctrl-break信号だけを送信します。 – Nettogrof

+0

だから私は、プロセスIDを見つけて(おそらく)POSIX関数などを使ってSIGINTを送る必要があると思います。 –

5

多くの試行の後、今私が好きな解決策を見つけました。 は基本的に、それは次のように動作します。 1.あなたは 2パスの代わりにCtrl-C送信SendSignal.exeを少し変更したバージョン、このPID開始したプロセスのプロセスIDを取得Ctrlキーをブレーク

両方のステップはまっすぐ進むわけではありませんが、ほとんどありません。 の場合1. PIDを取得する必要があります。 Javaはそれを得るためのネイティブな方法を提供しません。 これを行う方法については、いくつかのスレッドで議論しています。 私はここで名前に必要なものを決めました(下記のコードでgetProcessIDs()を参照)。

2.では、CTRL-Cを特定のPIDに送信するツールが必要です。ここでもJavaはこれをしません。 これを行うにはさまざまな方法があります(たとえば、Pythonなどのラッパーを使用していますが、すべてがやや複雑です)。一番簡単なのは、ジョブを実行するのに.exe-Fileを使うことです。このために、私はSendSingal.exeを修正しました。ここでソースコードを入手することができます:1. "BREAK"(小文字も含む)のすべてを "C"で置き換え、再コンパイルするだけです。

exeの名前を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を添付したいと思いますが、私は許可されていないと思います。あなたはこのコードをすることができますtaskkilljavaを終了するには実行しているCPP-コンパイラ...

+0

これは非常に興味深いです。共有してくれてありがとう。 – soulseekah

0

を持っている場合はとにかく、変更内容はシンプルでストレートフォワードです:

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

・ホープこのヘルプ!

関連する問題