Using CMD as a Process

2019-01-29 09:02发布

I'm trying to run commands straight through the CMD on Windows (Terminal on Linux). I have the following code. It's acting very strangely. First, when run the program does not print anything. Second, when debugged and stepped through, the program prints the default CMD text and input line. Finally, I can't seem to write to the CMD so it'll execute commands. Here's my code. I'm guessing it may be a threading issue, but I'm not familiar with Runtime.

    Runtime r = Runtime.getRuntime();
    try {
        Process p = r.exec("cmd");
        InputStream iStream = p.getInputStream();
        BufferedReader sReader = new BufferedReader(new InputStreamReader(iStream));
        while(sReader.ready()) {
            System.out.print((char)sReader.read());
        }

        OutputStream oStream = p.getOutputStream();
        BufferedWriter sWriter = new BufferedWriter(new OutputStreamWriter(oStream));
        sWriter.write("mkdir test");
        sWriter.newLine();

        while(sReader.ready()) {
            System.out.print((char)sReader.read());
        }
    } catch(Exception e) {
        e.printStackTrace();
    }

And my output when debugged and stepped through, (no output displayed when its run)

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

D:\workspaces\Maven\Command Line>

6条回答
Viruses.
2楼-- · 2019-01-29 09:17

There could be a couple of things going on. One is that arguments are not getting passed correctly the way you are executing the process. The other, like @zacheusz mentioned, is that output may be coming out from the error stream instead of the input stream.

ProcessBuilder helps with both these things, allowing easy construction of a list of commands and the ability to merge input and error stream. I recommend trying using it:

Process p = null;
try {
    List<String> cmd = new LinkedList<String>();
    cmd.add("executable");
    cmd.add("-arg1");
    cmd.add("value1");
    cmd.add("-arg2");
    ProcessBuilder pb = new ProcessBuilder(cmd);
    pb.redirectErrorStream(true);
    p = pb.start();
    BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
    while (input.ready()) {
        String line = input.readLine();
        System.out.println("From process: "+line);
    }
    input.close();
} catch (IOException e) {
    this.logMessage("IOException caught: "+e.getMessage());
    e.printStackTrace();
}
查看更多
等我变得足够好
3楼-- · 2019-01-29 09:18

cmd tries to run a command prompt ,

to run the command properly you need the following command line

cmd.exe -c ipconfig.exe

the -c means run the command on the rest of the command line

查看更多
forever°为你锁心
4楼-- · 2019-01-29 09:22

You can execute commands without actually hard coding cmd.exe into the code.

public static void main(String[] args) {

      //cmd = the command youw ill be using            
    String cmd = "ipconfig";      
    Runtime r = Runtime.getRuntime();      
    Process p;   
    try {       
        p = r.exec(cmd);

    BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));    
    String inputLine;       
    while ((inputLine = in.readLine()) != null) {     
        System.out.println(inputLine);
          }       
    }     


catch (IOException ex) {      
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);  
             }
       }
查看更多
Juvenile、少年°
5楼-- · 2019-01-29 09:24

Typically cmd or terminal are responsible for setting up standard io for the programs they execute, so I don't think you can just communicate with them via input/output stream. In case of Linux it's actually the shell run inside terminal that executes commands, not terminal itself. Windows probably does some funky things, too.

查看更多
冷血范
6楼-- · 2019-01-29 09:35

I found this code on the net years ago. I cant remember where. It's pretty old so there might be something better out there now.

 private void executeCommand(String cmd) {
        try {
            Runtime rt = Runtime.getRuntime();

            Process proc = rt.exec(cmd);

            // any error message?
            StreamHandler errorGobbler = new StreamHandler(proc.getErrorStream(), "ERR");

            // any output?
            StreamHandler outputGobbler = new StreamHandler(proc.getInputStream(), "OUT");

            // kick them off
            errorGobbler.start();
            outputGobbler.start();

            // any error???
            int exitVal = proc.waitFor();
            System.out.println("ExitValue: " + exitVal);
        } catch (Exception e) {
            e.printStackTrace();
        }


    }

And the class:

import java.util.*;
import java.io.*;

public class StreamHandler extends Thread {
    InputStream is;
    String type;
    OutputStream os;

    StringBuffer output;

    StreamHandler(InputStream is, String type) {
        this(is, type, null);
    }

    StreamHandler(InputStream is, String type, OutputStream redirect) {

        this.is = is;
        this.type = type;
        this.os = redirect;
        output = new StringBuffer(100);
    }

    public void run() {
        try {
            PrintWriter pw = null;
            if (os != null)
                pw = new PrintWriter(os);

            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line=null;
            while ( (line = br.readLine()) != null) {
                if (pw != null)
                    pw.println(line);
                System.out.println(type + ">" + line);
            }
            if (pw != null)
                pw.flush();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
    }
}
查看更多
趁早两清
7楼-- · 2019-01-29 09:36

You need to do this work in a Thread. For example to log the standard output:

Process process = Runtime.getRuntime().exec(command);
LogStreamReader lsr = new LogStreamReader(process.getInputStream());
Thread thread = new Thread(lsr, "LogStreamReader");
thread.start();


public class LogStreamReader implements Runnable {

    private BufferedReader reader;

    public LoggingStreamReader(InputStream is) {
        this.reader = new BufferedReader(new InputStreamReader(is));
    }

    public void run() {
        try {
            String line = reader.readLine();
            while (line != null) {
                System.out.println(line);
                line = reader.readLine();
            }
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Then you need a second thread for input handling. And you might want to deal with stderr just like stdout.

查看更多
登录 后发表回答