12

Java 9 provied pretty way to get information of the Process, but I still don't know how to get the CommandLine & arguments of the process:

Process p = Runtime.getRuntime().exec("notepad.exe E:\\test.txt");
ProcessHandle.Info info = p.toHandle().info();
String[] arguments = info.arguments().orElse(new String[]{});
System.out.println("Arguments : " + arguments.length);
System.out.println("Command : " + info.command().orElse("")); 
System.out.println("CommandLine : " + info.commandLine().orElse(""));

Result:

Arguments : 0
Command : C:\Windows\System32\notepad.exe
CommandLine : 

But I am expecting:

Arguments : 1
Command : C:\Windows\System32\notepad.exe
CommandLine : C:\Windows\System32\notepad.exe E:\\test.txt
Viet
  • 3,121
  • 1
  • 13
  • 33
  • 1
    Just to debug further, could you try replacing your ProcessHandler `p.toHandle()` with `ProcessHandle.current()` and execute to see, if you get some values in the expected fields? Mostly of the interest to see if the process handler of your current Process is appropriate or not. – Naman Oct 16 '17 at 10:19
  • Not lucky, still same. – Viet Oct 16 '17 at 10:23

3 Answers3

10

Seems this was reported in JDK-8176725. Here is the comment describing the issue:

The command line arguments are not available via a non-privileged API for other processes and so the Optional is always empty. The API is explicit that the values are OS specific. If in the future, the arguments are available by a Window APIs, the implementation can be updated.

BTW, the info structure is filled by native code; the assignments to the fields do not appear in the Java code.

M A
  • 65,721
  • 13
  • 123
  • 159
  • Yes, seem this worked on Linux, MacOS but not in Window now. – Viet Oct 16 '17 at 10:27
  • Not very sure about the resolution of that bug, but it seems like as marked that would be taken up as a *Future Project*. – Naman Oct 16 '17 at 11:06
3

JDK-8176725 indicates that this feature is not implemented yet for Windows. Here is an easy but slow workaround:

  /**
   * Returns the full command-line of the process.
   * <p>
   * This is a workaround for
   * <a href="https://stackoverflow.com/a/46768046/14731">https://stackoverflow.com/a/46768046/14731</a>
   *
   * @param processHandle a process handle
   * @return the command-line of the process
   * @throws UncheckedIOException if an I/O error occurs
   */
  private Optional<String> getCommandLine(ProcessHandle processHandle) throws UncheckedIOException {
    if (!isWindows) {
      return processHandle.info().commandLine();
    }
    long desiredProcessid = processHandle.pid();
    try {
      Process process = new ProcessBuilder("wmic", "process", "where", "ProcessID=" + desiredProcessid, "get",
        "commandline", "/format:list").
        redirectErrorStream(true).
        start();
      try (InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
           BufferedReader reader = new BufferedReader(inputStreamReader)) {
        while (true) {
          String line = reader.readLine();
          if (line == null) {
            return Optional.empty();
          }
          if (!line.startsWith("CommandLine=")) {
            continue;
          }
          return Optional.of(line.substring("CommandLine=".length()));
        }
      }
    } catch (IOException e) {
      throw new UncheckedIOException(e);
    }
  }
Gili
  • 76,473
  • 85
  • 341
  • 624
  • Excellent workaround. To turn that into an array of strings equivalent to `info.arguments()`, one has then to tokenize the string, paying attention to quoted strings, e.g. using https://stackoverflow.com/questions/3366281/tokenizing-a-string-but-ignoring-delimiters-within-quotes#3366634 ; and then drop the first element which is the command name. – 0__ Apr 06 '21 at 13:46
1

Try to use ProcessBuilder instead of Runtime#exec()

Process p = new ProcessBuilder("notepad.exe", "E:\\test.txt").start();

Or another way to create a process :

Process p = Runtime.getRuntime().exec(new String[] {"notepad.exe", "E:\\test.txt"});
Naman
  • 23,555
  • 22
  • 173
  • 290
Mykola Yashchenko
  • 4,315
  • 3
  • 33
  • 45