Write to input stream of opened terminal - java

I am having trouble writing to a command prompt that I can open via ProcessBuilder.
I have the following:
public class Terminal {
public static void main(String[] args) {
List<String> launch = new ArrayList<String>();
launch.add("cmd");
launch.add("/c");
launch.add("start");
launch.add("cmd.exe");
launch.add("/k");
try {
ProcessBuilder builder = new ProcessBuilder(launch);
Process process = builder.start();
OutputStream stdin = process.getOutputStream();
InputStream stdout = process.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(stdout));
BufferedWriter w = new BufferedWriter(new OutputStreamWriter(stdin));
w.write("dir");
w.flush();
w.close();
}
catch (IOException io) {
io.printStackTrace();
}
}
}
And this successfully opens a new Windows command prompt. But it never writes dir to it. The prompt just opens and only displays the directory from which java Terminal was issued.
How can I actively write to a terminal opened via a Process?
Edit:
If I change the command string list to "cmd.exe /k start dir" then the newly spawned command prompt does in fact issue the "dir" command and display it in the new terminal. I cannot seem to find the correct manner to access the stream for writing new commands to it.
public class Terminal {
public static void main(String[] args) {
List<String> launch = new ArrayList<String>();
launch.add("cmd");
launch.add("/k");
launch.add("start");
launch.add("dir");
try {
Process p = new ProcessBuilder(launch).start();
}
catch (IOException io) {
io.printStackTrace();
}
}
}

Lets take a look at what cmd /c start cmd /k does:
cmd /c starts a command prompt, executes the following commands, then exits.
start spawns a new process with the given commands
cmd /k expects a command (which you dont provide), executes it, then remains open
So: You start two instances of cmd. The second instance is started using start, which spawns a new process. You expect "dir" to show up in the second process, while it is being written to the first. Unfortunately, the first terminates immediately after calling start since you started it with /c.
Try changing /c to /k, then the "dir" should show up in the first window.

Related

Open a new command prompt and send commands from a Java program running in a command prompt

I have a Java program running in a command prompt (A) and would like to open a new command prompt (B), run some commands in B, and then close the B command prompt window.
I have been using these posts as reference:
Create a new cmd.exe window from within another cmd.exe prompt
How to open a command prompt and input different commands from a java program
I was able to open a command prompt from my Java program, How to run some exe in this command prompt using java code?
pass multiple parameters to ProcessBuilder with a space
Start CMD by using ProcessBuilder
Here is my code:
public static void startCMD(String appName) {
// init shell
String[] cmd = new String[]{"cmd.exe", "/C", "start"};
ProcessBuilder builder = new ProcessBuilder(cmd);
Process p = null;
try {
p = builder.start();
} catch (IOException e) {
System.out.println(e);
}
// get stdin of shell
BufferedWriter p_stdin = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
// execute the desired command (here: ls) n times
try {
// single execution
p_stdin.write("C:");
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("cd C:\\" + appName);
p_stdin.newLine();
p_stdin.flush();
p_stdin.write("sbt \"run 8080\"");
p_stdin.newLine();
p_stdin.flush();
} catch (IOException e) {
System.out.println(e);
}
// finally close the shell by execution exit command
try {
p_stdin.write("exit");
p_stdin.newLine();
p_stdin.flush();
} catch (IOException e) {
System.out.println(e);
}
// write stdout of shell (=output of all commands)
Scanner s = new Scanner(p.getInputStream());
while (s.hasNext()) {
System.out.println(s.next());
}
s.close();
}
The code above opens a new command prompt (B), but none of the commands are entered in this new command prompt (B). The current Java program just hangs in the command prompt (A).
I know I am missing some commands and parameters to have the command prompt (B) to close when the process is finished.
Is there a better way to build this?
I appreciate the help.

Execute commands in CMD on Windows with Java code

I want to write a Java code that would perform commands in Windows CMD.
I looked through the site and found out how to send and work with single request. For example create new Process and in execute ("cmd /c dir") then using input stream I can get the answer that is displayed.
How to open the process of cmd and let the user to enter cmd commands?
For example, I open application and it directly opens cmd process, then user can type "dir" and get the output.
After type "cd ../../"
and after type "dir" again and get the output with new path containment.
If it can be performed then how to do it? Or in order to perform this need to open each time a new process and execute ("cmd /c some_reqests")?
Nice question, you can in fact call cmd as a new process and use standard input and standard output to process data.
The tricky part is knowing when the stream from a command has ended.
To do so I used a string echoed right after the command (dir && echo _end_).
In practice I think it would be better to simply start a process for each task.
public class RunCMD {
public static void main(String[] args) {
try {
Process exec = Runtime.getRuntime().exec("cmd");
OutputStream outputStream = exec.getOutputStream();
InputStream inputStream = exec.getInputStream();
PrintStream printStream = new PrintStream(outputStream);
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream,"utf-8"));
printStream.println("chcp 65001");
printStream.flush();
printStream.println("dir && echo _end_");
printStream.flush();
for(String line=reader.readLine();line!=null;line=reader.readLine()){
System.out.println(line);
if(line.equals("_end_")){
break;
}
}
printStream.println("exit");
printStream.flush();
for(String line=reader.readLine();line!=null;line=reader.readLine()){
System.out.println(line);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
try this
Process p = Runtime.getRuntime().exec("ps -ef");
found it at http://alvinalexander.com/java/edu/pj/pj010016

running multiple cmd commands through java separated by some another code

I want to start a cmd command, then after the first command is done, I want to run a code to adjust some text in a file, then execute another command on the same cmd window. I don't know how to do that and everywhere I looked the answer is for the commands after each other which is not this case. the code for editing the text works fine without starting the cmd but if I execute the cmd command it does not change. code below.
public static void main(String[] args)throws IOException
{
try
{
Main m1 = new Main();
Process p= Runtime.getRuntime().exec("cmd /c start C:/TERRIERS/terrier/bin/trec_setup.bat");
p.waitFor();
/*code to change the text*/
m1.answerFile(1);
m1.questionFile(1);
/**********************/
//code to add another command here (SAME WINDOW!)
/************************/
}
catch(IOException ex){
}
catch(InterruptedException ex){
}
Execute cmd and send your command lines (.bat) to the standard input.
Process p = Runtime.getRuntime().exec("cmd");
new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null)
System.out.println(line);
} catch (Exception e) {
e.printStackTrace();
}
}).start();
try (PrintStream out = new PrintStream(p.getOutputStream())) {
out.println("C:/TERRIERS/terrier/bin/trec_setup.bat");
out.println("another.bat");
// .....
}
p.waitFor();
For starters, the \C option terminates CMD after executing the initial command. Use \K instead.
You won't be able to use waitFor() to detect when the initial command is done, because if you wait until the CMD terminates, you won't be able to re-use the same process.
Instead, you'll need to read the output of CMD process to detect when the batch file is complete and you are prompted for another command. Then write the next command line that you want to execute though the input stream of the Process.
Sounds like a pain. Why would do you need to use the same window?

Runtime.getRuntime().exec could not execute/show Tabtip.exe

I've set this OnClick method in JavaFX SceneBuilder on a text field that will pop up the Windows 8 touch keyboard if the user select the textfield. However it seems to be nothing happen when I click on the textfield but when I try to check Tabtip.exe in the task manager, it did shown up there. The codes are:
try
{
Runtime rt = Runtime.getRtuntime();
rt.exec( "cmd /c C:\\Programs Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe");
}
catch
{
ex.printStackTrace();
}
There is not errors triggered or whatsoever, and TabTip.exe is running in task manager, but the pop up keyboard does not show up, anyone has any solution to this? Thanks!
Whenever you want to execute a command which contains spaces in command prompt, you have to wrap it in double quotes.
Like this:
String commandStr = "cmd /c \"C:\\Program Files\\Common Files\\Microsoft Shared\\ink\\mip.exe\"";
rt.exec( commandStr );
And In addition to that, if you want to know your errors, you can get error stream from object of class Process which is returned by runtimeObject.exec().
String commandStr = "cmd /c C:\\Programs Files\\Common Files\\Microsoft Shared\\ink\\TabTip.exe"; // Like you did
InputStream is = rt.exec( commandStr ).getErrorStream();
int b;
while((b=(is.read()))!=-1)
System.out.print((char)b);
}
Please do like this. For me it is ok in window10 with javaFx application.
ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", "\"C:\\Program Files\\Common Files\\microsoft shared\\ink\\TabTip.exe");
builder.redirectErrorStream(true);
Process p;
try
{
p = builder.start();
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line;
while (true)
{
line = r.readLine();
if (line == null)
{
break;
}
System.out.println(line);
}
}
catch (IOException e)`enter code here`
{
// TODO Auto-generated catch block
e.printStackTrace();
}`enter code here`
The only way to run the TabTip.exe is to run the software on Admin mode.
I found the following batch code on the internet.
How to Use On-Screen and Touch Keyboard Instead of Spiral Keyboard
tasklist | find /I "TabTip.exe" >NUL && (taskkill /IM "TabTip.exe" /T)
start "" "TabTip.exe"
That code kills the TabTip process and executes a new TabTip.
In my case, I created a file called keyboard.bat and added the previous example.
In java, I created a method in order to read this file in the same folder.
That is my code
try{
File file = new File("keyboard.bat");
Runtime.getRuntime().exec(file.getAbsolutePath());
}catch(IOException ex){
Logger.getLogger(RunGazePoint.class.getName()).log(Level.SEVERE, null, ex);
}
after that, I compile my app and wrap it in executable mode with launch4j software.
Another way Is to execute by command, If you are using a multithreaded the system can avoid the lecture of file and not execute the software.
create two methods in order to kill and call the keyboard.
//hide the Keyboard
String[] array = new String[]{"cmd.exe","/c","taskkill /IM \"TabTip.exe\" /F\n" +
""};
Runtime.getRuntime().exec(array);
//Show the keyboard
String[] array = new String[]{"cmd.exe","/c","start \"\" \"TabTip.exe\""};
Runtime.getRuntime().exec(array);

how to launch a shell script in a new gnome terminal, from a java program

I'm trying to run a shell script (say myscript.sh) from a java program.
when i run the script from terminal, like this :
./myscript.sh
it works fine.
But when i call it from the java program, with the following code :
try
{
ProcessBuilder pb = new ProcessBuilder("/bin/bash","./myScript.sh",someParam);
pb.environment().put("PATH", "OtherPath");
Process p = pb.start();
InputStreamReader isr = new InputStreamReader(p.getInputStream());
BufferedReader br = new BufferedReader(isr);
String line ;
while((line = br.readLine()) != null)
System.out.println(line);
int exitVal = p.waitFor();
}catch(Exception e)
{ e.printStackTrace(); }
}
It doesnt goes the same way.
Several shell commands (like sed, awk and similar commands) get skipped and donot give any output at all.
Question : Is there some way to launch this script in a new terminal using java.
PS : i've found that "gnome-terminal" command launches a new terminal in shell,
But, i'm unable to figure out, how to use the same in a java code.
i'm quite new to using shell scripting. Please help
Thanks in advance
In java:
import java.lang.Runtime;
class CLI {
public static void main(String args[]) {
String command[] = {"/bin/sh", "-c",
"gnome-terminal --execute ./myscript.sh"};
Runtime rt = Runtime.getRuntime();
try {
rt.exec(command);
} catch(Exception ex) {
// handle ex
}
}
}
And the contents of the script are:
#!/bin/bash
echo 'hello!'
bash
Notes:
You'll do this in a background thread or a worker
The last command, in the shell script, is bash; otherwise execution completes and the terminal is closed.
The shell script is located in the same path as the calling Java class.
Don't overrwrite your entire PATH...
pb.environment().put("PATH", "OtherPath"); // This drops the existing PATH... ouch.
Try this instead
pb.environment().put("PATH", "OtherPath:" + pb.environment().get("PATH"));
Or, use the full directories to your commands in your script file.
You must set your shell script file as executable first and then add the below code,
shellScriptFile.setExecutable(true);
//Running sh file
Process exec = Runtime.getRuntime().exec(PATH_OF_PARENT_FOLDER_OF_SHELL_SCRIPT_FILE+File.separator+shellScriptFile.getName());
byte []buf = new byte[300];
InputStream errorStream = exec.getErrorStream();
errorStream.read(buf);
logger.debug(new String(buf));
int waitFor = exec.waitFor();
if(waitFor==0) {
System.out.println("Shell script executed properly");
}
This worked for me on Ubuntu and Java 8
Process pr =new ProcessBuilder("gnome-terminal", "-e",
"./progrm").directory(new File("/directory/for/the/program/to/be/executed/from")).start();
The previous code creates a new terminal in a specificied directory and executes a command
script.sh Must have executable permissions
public class ShellFileInNewTerminalFromJava {
public static void main(String[] arg) {
try{
Process pr =new ProcessBuilder("gnome-terminal", "-e", "pathToScript/script.sh").start();
}catch(Exception e){
e.printStackTrace();
}
}
}

Categories