The following method starts the cmd in Windows and it takes a parameter of the command which need to be run.
I have tested this method using the following commands: net users and it worked fine and it printed the users accounts. but if I run the dir command I get the following error:
java.io.IOEXception:
Cannot run program "dir": CreateProcess error=2, The system cannot find the file specified (in java.lang.ProcessBuilder)
Code :
private String commandOutPut;
public void startCommandLine(String s) throws IOException{
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec(s); // you might need the full path
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String commandOutPut;
while ((commandOutPut = br.readLine()) != null) {
this.commandOutPut = this.commandOutPut + "\n" + commandOutPut;
}
System.out.println(this.commandOutPut);
}
Well, obviously, your method does not start cmd. How did you get this notion?
The net command is a standalone command so it runs just fine, but the dir command is not standalone, it is an internal command of cmd.exe, so you cannot run it without launching cmd.exe to execute it.
To get it to work you will have to pass not dir but cmd.exe /c dir or something like that.
Don't know if this perception can help you. But, seems that "net users" are recognized as Windows command, since "Execute" dialog can run it.
But, for some reason, the "dir" command aren't. When try to run, Windows responds that command was not found.
Additionaly, I tried run Command with inline arguments too, but the arguments are simply ignored. (sorry for bad english)
My best guess is that this is because "net" is a real executable (there is a file WINDIR\System32\net.exe"), while "dir" is a builtin command of the command interpreter - it has no executable and is directly executed within cmd.exe.
Howevever you may get around this be invoking "dir" command inside the cmd process. The syntax - as per Microsoft docs - is:
cmd /c dir
There are also some related answers on the site:
How to execute cmd commands via Java
Run cmd commands through java
You can use the following code for this
import java.io.*;
public class demo
{
public static void main(String args[])
{
try
{
Process pro=Runtime.getRuntime().exec("cmd /c dir");
pro.waitFor();
BufferedReader redr=new BufferedReader(
new InputStreamReader(pro.getInputStream())
);
String ln;
while((ln = redr.readLine()) != null)
{
System.out.println(ln);
}
}
catch(Exception e) {}
System.out.println("Done");
}
}
Related
I use terminal command "java -jar secondApp.jar" inside my java file to start a secondApp.jar.
I need secondApp.jar to run even if first app is killed.
This scenario works perfectly in windows environment. But when I test this in linux environment(Ubuntu 16.04) it seems that killing the first process kills the both processes.
This is the code I use to start the second app.
String command = "java -jar secondApp.jar"
Process process = Runtime.getRuntime().exec(command);
What am I doing wrong?
Prepare a batch file and a linux script file with the desired java command, then try this:
if (SystemUtils.IS_OS_WINDOWS) {
// run batch file
String batchFullPath = new File("C:\\myBatchFile.bat").getAbsolutePath();
Runtime.getRuntime().exec("cmd /C start " + batchFullPath);
} else if (SystemUtils.IS_OS_LINUX) {
// run linux script
String scriptFullPath = new File("~/myScriptFile.sh").getAbsolutePath();
File workingDir = new File("~");
Runtime.getRuntime().exec("/usr/bin/xterm " + scriptFullPath, null, workingDir);
} else {
throw new RuntimeException("Unsupported Operating System");
}
(Using xterm as it is fairly safe to assume every Linux machine has it installed)
I have a seemingly trivial problem: I want to start a terminal from a java process and give the terminal one or two commands.
I have a simple example code, that works perfectly on windows with CMD. But I have not been able to achieve the same exact behavior on a Linux nor a Mac OS machine.
I am aware, that the command needs to be changed, but unfortunately I have not been able to pass a string of arguments to a terminal on Mac.
Here the working code for windows:
import java.lang.ProcessBuilder.Redirect;
public class ExecTest {
public static void main(String[] args){
String cmd = "cmd /c start cmd.exe /K \"echo hello && echo bye\"";
try {
Process p = Runtime.getRuntime().exec(cmd);
p.waitFor();
} catch (Exception e) {
e.printStackTrace();
}
}
}
On lubuntu I have been able to create a terminal with this command:
lxterminal -l -e 'echo hello && echo bye && read'
But this only works if called by a terminal but not with the java process.
.
TLDR: What is the Linux and Mac equivalent of this command:
cmd /c start cmd.exe /K \"echo hello && echo bye\"
I suggest you use ProcessBuilder to benefit from easier output redirection and ability to consume it without using threads, and also pass the command as a String[] instead of flat String to be able to support the various wrapping approaches. If you prefer to stick with Runtime.exec(), it also supports String[], but the example below uses ProcessBuilder.
static int executeInTerminal(String command) throws IOException, InterruptedException {
final String[] wrappedCommand;
if (isWindows) {
wrappedCommand = new String[]{ "cmd", "/c", "start", "/wait", "cmd.exe", "/K", command };
}
else if (isLinux) {
wrappedCommand = new String[]{ "xterm", "-e", "bash", "-c", command};
}
else if (isMac) {
wrappedCommand = new String[]{"osascript",
"-e", "tell application \"Terminal\" to activate",
"-e", "tell application \"Terminal\" to do script \"" + command + ";exit\""};
}
else {
throw new RuntimeException("Unsupported OS ☹");
}
Process process = new ProcessBuilder(wrappedCommand)
.redirectErrorStream(true)
.start();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line); // Your superior logging approach here
}
}
return process.waitFor();
}
Tested on 3 operating systems. The 3 booleans is{Windows|Linux|Mac} are unexplained here as OS detection is another topic, so for the example I kept it simple and handled out of the method.
The ProcessBuilder is configured to redirect stderr to stdout, so that a single stream needs to be read. That stream is then read and logged, because you must consume stderr and stdout, in case the Terminal itself prints stuff (not the command you are running in the Terminal, this is about what the Terminal itself prints), if it prints too much you risk getting the process to block indefinitely, waiting for the buffer to be read. See this nice answer.
For macOS if the command you pass is always a single executable script, you could also use {"open", "-a", "Terminal", command}, but that will not work with echo hello && echo bye. Similarly you could use {"/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal", command}, which would get you a second instance of the app running, but with same limitations.
Final note: you can offer a reasonable basic implementation, but you'll probably need to make it configurable to allow alternative terminal applications (especially on Linux where it varies a lot).
String[] cmd = {"echo", "hello", "&&", "echo", "hi"};
Runtime.getRuntime().exec(cmd);
There are multiple ways to do this, but this should work for you. Executables on Mac should run automatically in Terminal.
Possibly similar to: How To Run Mac OS Terminal Commands From Java (Using Runtime?)
If anything they have a few methods for running scripts in the terminal.
In my Java application, I want to run a batch file that calls "scons -Q implicit-deps-changed build\file_load_type export\file_load_type"
It seems that I can't even get my batch file to execute. I'm out of ideas.
This is what I have in Java:
Runtime.
getRuntime().
exec("build.bat", null, new File("."));
Previously, I had a Python Sconscript file that I wanted to run but since that didn't work I decided I would call the script via a batch file but that method has not been successful as of yet.
Batch files are not an executable. They need an application to run them (i.e. cmd).
On UNIX, the script file has shebang (#!) at the start of a file to specify the program that executes it. Double-clicking in Windows is performed by Windows Explorer. CreateProcess does not know anything about that.
Runtime.
getRuntime().
exec("cmd /c start \"\" build.bat");
Note: With the start \"\" command, a separate command window will be opened with a blank title and any output from the batch file will be displayed there. It should also work with just `cmd /c build.bat", in which case the output can be read from the sub-process in Java if desired.
Sometimes the thread execution process time is higher than JVM thread waiting process time, it use to happen when the process you're invoking takes some time to be processed, use the waitFor() command as follows:
try{
Process p = Runtime.getRuntime().exec("file location here, don't forget using / instead of \\ to make it interoperable");
p.waitFor();
}catch( IOException ex ){
//Validate the case the file can't be accesed (not enought permissions)
}catch( InterruptedException ex ){
//Validate the case the process is being stopped by some external situation
}
This way the JVM will stop until the process you're invoking is done before it continue with the thread execution stack.
Runtime runtime = Runtime.getRuntime();
try {
Process p1 = runtime.exec("cmd /c start D:\\temp\\a.bat");
InputStream is = p1.getInputStream();
int i = 0;
while( (i = is.read() ) != -1) {
System.out.print((char)i);
}
} catch(IOException ioException) {
System.out.println(ioException.getMessage() );
}
ProcessBuilder is the Java 5/6 way to run external processes.
To run batch files using java if that's you're talking about...
String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);`
This should do it.
The executable used to run batch scripts is cmd.exe which uses the /c flag to specify the name of the batch file to run:
Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", "build.bat"});
Theoretically you should also be able to run Scons in this manner, though I haven't tested this:
Runtime.getRuntime().exec(new String[]{"scons", "-Q", "implicit-deps-changed", "build\file_load_type", "export\file_load_type"});
EDIT: Amara, you say that this isn't working. The error you listed is the error you'd get when running Java from a Cygwin terminal on a Windows box; is this what you're doing? The problem with that is that Windows and Cygwin have different paths, so the Windows version of Java won't find the scons executable on your Cygwin path. I can explain further if this turns out to be your problem.
Process p = Runtime.getRuntime().exec(
new String[]{"cmd", "/C", "orgreg.bat"},
null,
new File("D://TEST//home//libs//"));
tested with jdk1.5 and jdk1.6
This was working fine for me, hope it helps others too.
to get this i have struggled more days. :(
I had the same issue. However sometimes CMD failed to run my files.
That's why i create a temp.bat on my desktop, next this temp.bat is going to run my file, and next the temp file is going to be deleted.
I know this is a bigger code, however worked for me in 100% when even Runtime.getRuntime().exec() failed.
// creating a string for the Userprofile (either C:\Admin or whatever)
String userprofile = System.getenv("USERPROFILE");
BufferedWriter writer = null;
try {
//create a temporary file
File logFile = new File(userprofile+"\\Desktop\\temp.bat");
writer = new BufferedWriter(new FileWriter(logFile));
// Here comes the lines for the batch file!
// First line is #echo off
// Next line is the directory of our file
// Then we open our file in that directory and exit the cmd
// To seperate each line, please use \r\n
writer.write("cd %ProgramFiles(x86)%\\SOME_FOLDER \r\nstart xyz.bat \r\nexit");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// Close the writer regardless of what happens...
writer.close();
} catch (Exception e) {
}
}
// running our temp.bat file
Runtime rt = Runtime.getRuntime();
try {
Process pr = rt.exec("cmd /c start \"\" \""+userprofile+"\\Desktop\\temp.bat" );
pr.getOutputStream().close();
} catch (IOException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
// deleting our temp file
File databl = new File(userprofile+"\\Desktop\\temp.bat");
databl.delete();
The following is working fine:
String path="cmd /c start d:\\sample\\sample.bat";
Runtime rn=Runtime.getRuntime();
Process pr=rn.exec(path);
This code will execute two commands.bat that exist in the path C:/folders/folder.
Runtime.getRuntime().exec("cd C:/folders/folder & call commands.bat");
import java.io.IOException;
public class TestBatch {
public static void main(String[] args) {
{
try {
String[] command = {"cmd.exe", "/C", "Start", "C:\\temp\\runtest.bat"};
Process p = Runtime.getRuntime().exec(command);
} catch (IOException ex) {
}
}
}
}
To expand on #Isha's anwser you could just do the following to get the returned output (post-facto not in rea-ltime) of the script that was run:
try {
Process process = Runtime.getRuntime().exec("cmd /c start D:\\temp\\a.bat");
System.out.println(process.getText());
} catch(IOException e) {
e.printStackTrace();
}
I need to execute the following Change directories commands into the cmd prompt, but using java to execute them. the dir command works fine , but not the cd ones. I have to execute them in a single cmd windows
cd inputDir
dir
cd outputDir
inputDir and outputDir are directories from the windows.
Java Snippet:
ArrayList<String> dosCommands = new ArrayList<String>();
Process p;
for (int i=0;i< dosCommands.size();i++){
p=Runtime.getRuntime().exec("cmd.exe /c "+dosCommands.get(i));
p.waitFor();
BufferedReader reader=new BufferedReader(new InputStreamReader(p.getInputStream()));
String line=reader.readLine();
while(line!=null)
{
System.out.println(line);
line=reader.readLine();
}
}
UPDATE
Changing the argument to cmd.exe /k instead of /c
p=Runtime.getRuntime().exec("cmd.exe /k "+dosCommands.get(i));
I had to remove the
p.waitFor();
method, because I was getting stucked in it.
Doing so, know I do get stucked in the
line.reader.readLine();
use
cmd.exe /K
Not
cmd.exe /c
You can find more about cmd params here
With /c, cmd finishes and exit. With /k, it does not exit.
__UPDATE__
What I mean is as follows:
cd inputDir
dir
cd outputDir
exit
Pay attention to the last line please.
__UPDATE 2__
Please use something similar in your code to find out what is the current working directory, according to running process:
public class JavaApplication1 {
public static void main(String[] args) {
System.out.println("Working Directory = " +
System.getProperty("user.dir"));
}
}
After that, let's make sure that the folders you are trying to cd to exists in that folder.
Try this experiment: Open a command window (using your mouse and/or keyboard, not with code). Now change to a different directory, with a command like cd \ or cd C:\Windows.
Then open a second command window. What is its current directory? Did it remember what you did in the first command window?
It didn't, because each time you run cmd.exe you are starting a new process, with its own current directory state.
In your code, you are executing a new cmd.exe process in each iteration of your for-loop. Each time you start a new cmd.exe, it has no awareness of what the current directory may be in other cmd.exe instances.
You can set the current directory in which a process executes:
String inputDir = "C:\\Users\\eleite\\Workspace\\RunCmd\\Petrel_Logs";
p = Runtime.getRuntime().exec("cmd.exe /c " + dosCommands.get(i),
null, inputDir);
If you want to
create process simulating console
and make this console execute few commands
and after these commands are executed continue code from main thread
then try this code
ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/k");
pb.redirectOutput(Redirect.INHERIT);//redirect process output to System.out
pb.redirectError(Redirect.INHERIT);//redirect process output to System.err
Process p = pb.start();
try(PrintWriter pw = new PrintWriter(new OutputStreamWriter(p.getOutputStream()), true)){
pw.println("dir");//execute command 1, for instance "dir"
pw.println("ver");//execute command 2, for instance "ver"
//... rest of commands
pw.println("exit");//when last command finished, exit console
}
p.waitFor();//this will make main thread wait till process (console) will finish (will be closed)
//here we place rest of code which should be executed after console after console process will finish
System.out.println("---------------- after process ended ----------------");
So if you want list of commands you want to execute simply place them here:
try(PrintWriter pw = new PrintWriter(new OutputStreamWriter(p.getOutputStream()), true)){
//here and execute them like
for (String command : dosCommands){
pw.println(command);
}
pw.println("exit");//when last command finished, exit console
}
I have been trying to get this program to run a class file that is located in /Library/Application Support/Adobe/Adobe PCD/cache/Main.class.
Yet every time I run the method below, It cannot find the file specified. I think that eclipse is looking for the file path above in the project folder. But the first command doesn't seem to work. Can Anyone help me? Is there another way to run the class file?
static Runtime r = Runtime.getRuntime();
public static void Run() {
try {
Runtime rt = Runtime.getRuntime();
String run = "/Library/Application Support/Adobe/Adobe PCD/cache/";
String[] command = {"java -cp " + run, "java Main"};
Process pr = rt.exec(command);
BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line=null;
while((line=input.readLine()) != null) {
System.out.println(line);
}
int exitVal = pr.waitFor();
System.out.println("Exited with error code "+exitVal);
} catch(Exception e) {
System.out.println(e.toString());
e.printStackTrace();
}
}
This tries to run a mythical program java -cp /Library/Application Support/Adobe/Adobe PCD/cache/ with argument java Main. java Main is an illegal name for a class too. Instead, have your command array be:
String[] command = {"java", "-cp", run, "Main"};
However, unless you have a Main class in the default package, simply add the run directory to your application's class path, and then call Main.main(), possibly playing games with standard input and output. There is no need to start a second JVM. Or, figure out what Main does, and call the classes it calls. Is there Javadoc for the Adobe code?
When the Ant task <zip> runs, Ant does not start a new VM or a command-line zip utility. Instead, the task's class calls methods in java.util.zip. You should do something similar.