Java 执行显示控制台窗口的命令,并获取进程的句柄

Java 执行显示控制台窗口的命令,并获取进程的句柄,java,command-line,process,Java,Command Line,Process,我正在尝试从Java运行一个命令,该命令将启动一个运行数分钟的进程。我只需要触发命令并获取进程句柄,然后继续循环中的其他操作。每隔一段时间,我必须监控该进程是否仍处于活动状态 我还需要显示console窗口,以便为用户显示进程的输出 目前,我尝试了运行时类和ProcessBuilder类中的方法来运行我的命令,但它们都没有帮助我实现目标 示例代码: //Changing the directory and running Maven exec: java command on the POM f

我正在尝试从Java运行一个命令,该命令将启动一个运行数分钟的进程。我只需要触发命令并获取进程句柄,然后继续循环中的其他操作。每隔一段时间,我必须监控该进程是否仍处于活动状态

我还需要显示console窗口,以便为用户显示进程的输出

目前,我尝试了运行时类和ProcessBuilder类中的方法来运行我的命令,但它们都没有帮助我实现目标

示例代码:

//Changing the directory and running Maven exec: java command on the POM file in that directory.

String cmd = "cd C:/Test & mvn exec:java"; 
String finalCmd = "cmd /c \""+ cmd +"\"";

Process process = Runtime.getRuntime().exec(finalCmd);
Thread.sleep(10);
boolean alive = process.isAlive();
variable alive的值为True,但我看不到进程已经启动。当程序执行完成时,流程才会开始,我不知道为什么会发生这种情况

另外,为了显示控制台窗口,我从google发现我需要使用以下命令:

String finalCmd = "cmd /c start cmd.exe /c \"" + cmd + "\"";
然而,有了它,进程立即启动,但我没有得到进程句柄,因为我发现活动变量显示为false


有人知道如何实现这一目标吗?如果不能同时执行这两项操作,我也可以,但至少我需要启动流程执行,并在代码中获取句柄以监控流程状态。

因为我不太了解您真正需要的是什么,所以我从java类(例如类a)中提供了一个全面的openning cmd示例启动另一个java类(类B)的进程,在类B通知类a它是否正在处理时从类B执行一些操作。所以,整个过程就是从命令promt中排除类B,类A启动了,并从类B发送信息到类A,通知它仍在运行

在我的示例中,我将
Main类
作为类A,将
myProcess类
作为类B。 正如您在下面的代码中所看到的,
Main类
正在打开cmd并正在执行
myProcess类
,然后
myProcess类
正在通过在
Main类
中创建的套接字发送有关进程的信息

//imports
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
//class
public class Main 
{
  //fields

  //methods


    public static void main(String[] args) throws Exception
    {

        Runtime run = Runtime.getRuntime();
        String new_dir = "C:\\Users\\Parsa\\Desktop\\New folder (2)";//imagine the directory of myProcess.class is in this folder
        startServer();
        run.exec("cmd.exe /c cd \""+new_dir+"\" & start cmd.exe /k \"java myProcess\"");

    }


    public static void startServer() 
    {
        Thread myThread = new Thread() 
        {
            @Override
            public void run() 
            {
                ServerSocket ss;// creating an open port for receiving data from network
                try {
                    ss = new ServerSocket(60010);//open port number 60010--> it can really be anything that is empty

                    Socket s = ss.accept();//Listens for a connection to be made to this socket and accepts it

                    BufferedReader in = new BufferedReader(
                            new InputStreamReader(s.getInputStream()));//get the inputstream and change it to a buffered reader in order to get a string from remote network
                    String line = null;
                    while ((line = in.readLine()) != null) //read the input
                    {
                        System.out.println(line);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };

        myThread.start();


    }

}
myProcess类:

顺便说一下,您需要通过命令提示符手动编译myProcess类,并从主类中执行myProcess.class文件

myProcess类是

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.Timer;
import java.util.TimerTask;

public class myProcess extends Thread
{
  //field

  //methods
    public static void main(String[] args) throws Exception
    {
        System.out.println("myProcess has started");
        startSender();

    }


    public static void startSender() 
    {
        Thread myThread = new Thread() 
        {
            @Override
            public void run() 
            {
                try 
                {
                    Socket s = new Socket("localhost", 60010);
                    BufferedWriter out = new BufferedWriter(
                            new OutputStreamWriter(s.getOutputStream()));

                    for(int i = 0 ; i<10 ; i++)
                    {
                        out.write("Process in running");
                        out.newLine();
                        out.flush();

                        Thread.sleep(200);
                    }
                    out.close();
                    //do whatever here
                    System.out.println("myProcess output");
                } 
                catch (Exception e) 
                {
                    e.printStackTrace();
                } 
            }
        };
        myThread.start();


        if(!myThread.isAlive())
        {
            System.out.println("myProcess has finished");
        }
    }
}
导入java.io.BufferedWriter;
导入java.io.IOException;
导入java.io.OutputStream;
导入java.io.OutputStreamWriter;
导入java.net.Socket;
导入java.net.URL;
导入java.net.URLConnection;
导入java.net.UnknownHostException;
导入java.util.Timer;
导入java.util.TimerTask;
公共类myProcess扩展了线程
{
//场
//方法
公共静态void main(字符串[]args)引发异常
{
System.out.println(“myProcess已启动”);
startSender();
}
公共静态无效startSender()
{
线程myThread=新线程()
{
@凌驾
公开募捐
{
尝试
{
套接字s=新套接字(“本地主机”,60010);
BufferedWriter out=新的BufferedWriter(
新的OutputStreamWriter(s.getOutputStream());

对于(int i=0;i这里发生的两件事情:

  • 我们需要将命令作为字符串标记传递给exec()命令
  • 我们需要等待进程以process.waitFor()退出,而不是休眠,这将阻止当前线程,因此如果您不想在另一个线程中执行此操作或使用ExecutorService
  • 建议检查waitFor()的输出值,查看我们的命令是否正确执行(值为0)或不正确(任何其他值, 执行不成功时,通常为正1)
  • 或者(要查看输出),我们需要重定向标准并在某个地方出错,比如说将其打印到console(),尽管您可以将其放入某个GUI窗口等的文件中
因此,至少应使用以下代码:

Process process = Runtime.getRuntime().exec(new String[] {"cmd", "/c", "cd", "C:\\dev", "&&", "dir"});
int outputVal = process.waitFor();
boolean alive = process.isAlive();
System.out.format("alive %s, outputVal: %d\n",alive, outputVal);
进一步建议:

  • 使用ProcessBuilder而不是runTime.exec(),它允许更多的控制 是自JDK1.5以来的推荐方式
  • 读取输入流
因此,代码将如下所示:

    List<String> cmdList = Arrays.asList("cmd", "/c", "cd", "C:\\dev", "&&", "dir");
    ProcessBuilder pb = new ProcessBuilder(cmdList);
    pb.redirectErrorStream(true); //redirect STD ERR to STD OUT
    Process process = pb.start();
    try (final BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
        String line = null;
        while ((line = br.readLine()) != null) {
              System.out.println("std-out-line: " + line);
        }
    }
    int outputVal = process.waitFor();
    System.out.format("outputVal: %d\n", outputVal);
List cmdList=Arrays.asList(“cmd”、“c”、“cd”、“c:\\dev”、“&&”、“dir”);
ProcessBuilder pb=新的ProcessBuilder(cmdList);
pb.redirectErrorStream(true);//将STD ERR重定向到STD OUT
Process进程=pb.start();
try(final BufferedReader br=new BufferedReader(new InputStreamReader(process.getInputStream())){
字符串行=null;
而((line=br.readLine())!=null){
System.out.println(“标准输出行:+行”);
}
}
int outputVal=process.waitFor();
System.out.format(“outputVal:%d\n”,outputVal);
由于waitFor()是一个阻塞调用,因此可以在单独的线程中或使用executorService执行此调用。此处的示例代码:

    final StringBuffer outputSb = new StringBuffer();
    ExecutorService executorService = null;
    try {
        executorService = Executors.newSingleThreadExecutor();
        final Future<Integer> future = executorService.submit(new Callable<Integer>() {

            @Override
            public Integer call() throws Exception {
                try (final BufferedReader br = new BufferedReader(
                        new InputStreamReader(process.getInputStream()))) {
                    String line = null;
                    while ((line = br.readLine()) != null) {
                        outputSb.append("std-out-line: ");
                        outputSb.append(line);
                        outputSb.append('\n');
                    }
                }
                int exitValue = process.waitFor();
                System.out.format("exitValue: %d\n", exitValue);

                return exitValue;
            }
        });

        while (!future.isDone()) {
            System.out.println("Waiting for command to finish doing something else..");
            Thread.sleep(1 * 1000);
        }

        int exitValue = future.get();
        System.out.println("Output: " + outputSb);

    } finally {
        executorService.shutdown();
    }
final StringBuffer outputSb=new StringBuffer();
ExecutorService ExecutorService=null;
试一试{
executorService=Executors.newSingleThreadExecutor();
final Future=executorService.submit(new Callable()){
@凌驾
公共整数调用()引发异常{
try(final BufferedReader br=new BufferedReader(
新的InputStreamReader(process.getInputStream())){
字符串行=null;
而((line=br.readLine())!=null){
outputSb.append(“标准输出行:”);
outputSb.追加(行);
outputSb.append('\n');
}
}
int exitValue=process.waitFor();
System.out.format(“exitValue:%d\n”,exitValue);
返回现有值;
}
});
public static void main( String[] args ) throws Exception {

    // Vars
    Process process;
    String output;

    // Execution
    process = Runtime.getRuntime().exec("cmd /c wmic process call create calc.exe | findstr ProcessId");
    output = readTrimmedOutput(process.getInputStream());
    System.out.println("Output from command: " + output);

    // Basic string manipulation to get process id
    String str_proc_id = output.split(" = ")[1].replace(";","");
    System.out.println("ProcessId is: " + str_proc_id);

    // Some thread delay that you can comment/uncomment for testing if running or not
    Thread.sleep(5000);

    // Finding if process is still running
    process = Runtime.getRuntime().exec("cmd /c wmic process get processid | findstr " + str_proc_id);
    output = readTrimmedOutput(process.getInputStream());

    boolean isRunning = output.contains(str_proc_id);
    System.out.println("Is process still running? " + isRunning);

}

private static String readTrimmedOutput(InputStream is) throws Exception {
    BufferedReader breader = new BufferedReader(new InputStreamReader(is));
    String line = breader.readLine();
    return line != null ? line.trim() : "";
}
Output from command: ProcessId = 6480;
ProcessId is: 6480
Is process still running? true
// Execution
String your_command = "cmd.exe /c \"dir\"";
process = Runtime.getRuntime().exec("cmd /c wmic process call create \"" + your_command + "\" | findstr ProcessId");