2009-12-02 29 views
14

Trong hệ điều hành Windows.Gửi Ctrl-C để xử lý mở bằng Java

Tôi bắt đầu một tiến trình con thông qua Runtime.getRuntime(). Exec(); Tôi muốn gửi "ctrl-c" đến quá trình dừng nó.

Tôi đã làm một ví dụ nhỏ, với Runtime.getRuntime(). Exec ("ping google.com -n 100000"); Mã này có thể được tìm thấy ở đó: http://pastebin.com/f6315063f

Cho đến giờ, tôi đã cố gắng gửi ký tự char '3' (ký tự ctrl-C) qua Process outputStream.

Dưới đây là một chút mã:

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

Tôi không muốn giết quá trình này, tôi chỉ muốn gửi một tín hiệu Ctrl-C. Tôi có thể làm như thế nào?

+0

Cuối cùng, bạn đang cố gắng đạt được điều gì? –

+0

Thực hiện trình bao bọc xung quanh DOS/windows3 cũ.1/win95 ứng dụng – Nettogrof

+0

nó sẽ làm việc nhưng bạn nên gửi phá vỡ chỉ một lần, làm điều đó hai lần rõ ràng là sẽ giết chết quá trình chính. –

Trả lời

6

Tôi tin rằng Ctrl-C bị bắt bởi vỏ và được dịch thành tín hiệu (SIGINT) được gửi đến quy trình cơ bản (trong trường hợp này là quá trình sinh sản của bạn).

Vì vậy, tôi nghĩ bạn sẽ cần có id quá trình và sau đó gửi tín hiệu thích hợp cho quá trình đó. This question dường như rất giống nhau và trỏ đến các nguồn tài nguyên sử dụng khác nhau.

+0

Tôi đã thấy câu hỏi đó nhưng SendSignal chỉ gửi tín hiệu ctrl-break. – Nettogrof

+0

Vì vậy, tôi nghĩ rằng sau đó bạn cần phải tìm id quá trình và gửi SIGINT qua (có lẽ) một chức năng POSIX hoặc tương tự. –

5

Sau rất nhiều thử nghiệm, tôi đã tìm thấy một giải pháp mà tôi thích bây giờ. Về cơ bản, nó hoạt động như sau: 1. Lấy ID tiến trình của quy trình mà bạn đã bắt đầu 2. Chuyển PID này sang phiên bản được sửa đổi của SendSignal.exe, sẽ gửi Ctrl-C thay vì Ctrl-Break

Cả hai bước không hoàn toàn thẳng về phía trước, nhưng gần như. Đối với 1. bạn cần lấy PID. Java không cung cấp bất kỳ cách nào để có được nó. Có một số chủ đề thảo luận về cách làm tốt nhất. Tôi quyết định cho một nơi bạn cần đến bây giờ tên (xem getProcessIDs() trong đoạn mã dưới đây).

Đối với 2. bạn cần có công cụ gửi CTRL-C đến một PID nhất định. Một lần nữa, Java không làm điều này. Có nhiều cách khác nhau để thực hiện điều đó (ví dụ: sử dụng trình bao bọc trong python hoặc như vậy), nhưng tất cả chúng đều hơi phức tạp. Tôi thấy dễ nhất là sử dụng .exe-File để thực hiện công việc. Đối với điều này, tôi sửa đổi SendSingal.exe. Bạn có thể lấy mã nguồn ở đây: 1. Sau đó, chỉ cần thay thế tất cả các lần xuất hiện của "BREAK" (cũng bằng chữ thường) bằng "C" và biên dịch lại.

Đổi tên exe thành SendSignalC.exe và đặt nó vào thư mục con ext \ của nơi bạn bắt đầu Java. Sau đó, hãy chạy mã bên dưới và gọi điện một cách vui vẻ, ví dụ: SendCTRLC.sendCtrlC ("tuyyourprogramiscall.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: Tôi rất muốn đính kèm SendSignalC.exe tại đây, nhưng tôi không nghĩ rằng mình được phép. Nhưng dù sao, những thay đổi rất đơn giản và thẳng về phía trước nếu bạn có một chạy cpp-trình biên dịch ...

+0

Điều này rất thú vị. Cám ơn vì đã chia sẻ. – soulseekah

0

Để chấm dứt, bạn có thể taskkilljava với mã này:

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

Hope trợ giúp này!

Các vấn đề liên quan