Search code examples
javacmdprocesstasklist

Runtime.exec() returning null


I have seen similiar questions on this site, but none of them seem to address/solve my problem, so I figured there is something specifically wrong with my program. I am trying to execute a very simple command, which is to take a string of a process name from a textfield input and concatenate it to a command to return and print the title of the window. This is my code:

        String line;
        Process p = null;
        try
        {
            String command = "tasklist /v /fo list /fi \"imagename eq  " + tf.getText().trim() + "*\"| find /i  \"window title:\"\n";
            p = Runtime.getRuntime().exec(command);

            BufferedReader input =
                    new BufferedReader(new InputStreamReader(p.getInputStream()));

            System.out.println(command);
            while ((line = input.readLine()) != null)
            {
                line = line.trim();
                System.out.println(line);

            }
            System.out.println("done");
        }
        catch (IOException ioException)
        {
            ioException.printStackTrace();
        }

However, the line returned by the InputStream is always null, even though if I put the command used in .exec() into cmd (I printed it so I know they are the exact same), it works properly, albeit after a 5 seconds or so of delay. I tried it with 2 different process names and they both worked on cmd, but not in this java program. This is the output of the above code, in case that helps (the blank line is presumably from the \n at the end of the command string):

tasklist /v /fo list /fi "imagename eq  notepad*"| find /i  "window title:"

done

I tried adding p.waitFor() after calling .exec(), but that didn't seem to change anything. So what am I doing wrong here?


Solution

  • You have two problems with launching the command. Firstly you are ignoring error stream so don't see the actual problem.

    Replace p = Runtime.getRuntime().exec(command); with ProcessBuilder to get access to error message:

    ProcessBuilder pb = new ProcessBuilder(command);
    pb.redirectErrorStream();
    p = pb.start();
    

    This will tell you that tasklist is not a process. Normally using full pathname would fix this type of error, but as you are using pipe the whole command must sent to to CMD.EXE to interpret pipe components correctly. Run CMD.EXE then your piped command:

    ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/c", command);
    pb.redirectErrorStream();
    p = pb.start();
    

    Prints:

    tasklist /v /fo list /fi "imagename eq  notepad*"| find /i  "window title:"
    
    Window Title: Notepad++
    done
    

    It's also easier to read STDOUT with simple transfer:

    try(var stdout = p.getInputStream()) {
        stdout.transferTo(System.out);  // or where-ever
    }