0

Background

I started a command prompt from a Java application. Now I want to input commands into the command prompt that was just generated. How can you run commands in the prompt that was just generated by the Java program?

What I've tried

My code creates a process that starts the command prompt. And then it gets the process's OutputStream to try and write to it. But I don't see any changes happening. It should just change directories and then run a series of commands in the new directory.

// Block that makes new command prompt
List<String> commands = new ArrayList<String>();
commands.add("cmd.exe");
commands.add("/c");
commands.add("start");
commands.add("cmd.exe");

// Block that creates a writer to write to new command prompt
ProcessBuilder pb = new ProcessBuilder(commands);
Process p = pb.start();
OutputStream os = p.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(os)); 

// Block that actually writes the commands
writer.write(String.format("cd %s\n", PATH);
writer.write(OTHER_COMMANDS); // I'm ommiting the other commands because there's a lot
writer.flush();
writer.close();

I'm unsure why the commands aren't written to the command prompt that pops up. I see that a new command prompt pops up, but the directory is unchanged from where it starts. How can I input commands into the prompt that I generate?

Gerald
  • 109
  • 9

3 Answers3

1

Your program ProcessBuilder gives you access to the stdin, stdout, and stderr of the process cmd.exe. Those are not the same things as the input and the output of a window and command prompt opened up by the program cmd.exe

There is an answer here regarding how to do it with c#: Create a cmd window and write to it from C# application

In Java I am not aware of a similar API, it might actually require using JNI or JNA in order to gain access to the Windows APIs you would need to use. The function you use (through JNI or JNA) would be the same https://learn.microsoft.com/en-us/windows/console/allocconsole referenced in that other answer. So that is one way to do it, but a full description of how to use either JNI or JNA is outside the scope of an answer here, should you choose to go that route.

Sean F
  • 4,344
  • 16
  • 30
1

When you're writing to p, you're writing to this command's standard input:

cmd.exe /c start cmd.exe

You're writing to the first cmd.exe. Which does not do anything except start the second one. It is not possible (at least not simple) to get a handle to the second process. You can use /K, and merge the commands with && after each other. For example:

commands.add("/K");
commands.add(String.join(" && ", OTHER_COMMANDS_AS_LIST));
CoderCharmander
  • 1,862
  • 10
  • 18
  • Would there be any way, then, to get the commands to run directly from the first ```cmd.exe```? (For cleaner code). I got this method to work, but it does seem more like a workaround rather than how it is intended. – Gerald May 20 '20 at 20:43
  • As my knowledge, it is not possible. – CoderCharmander May 20 '20 at 21:13
0

As far as I can see, you're trying to implement something vaguely similar to a remote shell (SSH without network and without encryption)...

This should work like you expect for a *nix-like shell, because those shells handle their standard input and output correctly, precisely for the case that they need to be redirected (over a network, or whatever).

The Windows cmd.exe is actually not a pure shell. It is a terminal emulator (the black window that appears on the screen) and the shell, in one process. That's why it doesn't get its input from stdin, and doesn't print its output on stdout. Instead, it listens to GUI keyboard events for input and handles them internally, and the output is displayed directly in the window, without writing it to stdout.

That's why there is no easy way to "remote control" a cmd.exe. It's just not made for that. You can try this with "proper" shells, like a Cygwin'ed bash.exe, or maybe PowerShell, or similar.

It's actually astonishing that the cmd.exe which was created as a quick'n'dirty "DOS window" some 20 years ago, is still surviving to this day and is actually used for production work...

Mike
  • 143
  • 5