Execute external program from Java (with cmd, Windows) - java

I've done many research for executing an external program (e.g. iTunes) by some simple code, however the suggestions did never work. Sometimes nothing happend, sometimes I got this error message:
English: Unable to find "Discord". Be sure the name is written correctly and try again.
My Code is the following:
try {
String name = (String) "start " + table.getValueAt(table.getSelectedRow(), table.getSelectedColumn());
ProcessBuilder p = new ProcessBuilder("cmd.exe", "cd /D %HOMEDRIVE%%HOMEPATH%/Desktop", "/c", name);
p.start();
} catch (Exception e) {
e.printStackTrace();
}
In my example I get the name of the external program from a JTable, this part is working fine. The ProcessBuilder is changing the directory to the desktop first. Then the external program should be executed by the start <program name> command. With this code I get the mentioned error message.
If you have a solution with cmd, please include changing the directory to the desktop.

You should pass each argument as a single entry to ProcessBuilder. In your current code, you sometimes take multiple arguments together (like cd /D %HOME...). Try passing every argument as it's own parameter, including the command to start and its argument:
String name = (String) table.getValueAt(table.getSelectedRow(), table.getSelectedColumn());
ProcessBuilder p = new ProcessBuilder("cmd.exe", "cd", "/D", "%HOMEDRIVE%%HOMEPATH%/Desktop", "/c", "start", name);

According to: cmd.exe,
/D Ignore registry AutoRun commands
HKLM | HKCU \Software\Microsoft\Command Processor\AutoRun
Did you mean start.exe /D not cmd.exe /D?
and also they told that
If /C or /K is specified, then the remainder of the command line is processed as an immediate command in the new shell. Multiple commands separated by the command separator '&' or '&&' are accepted if surrounded by quotes.
Did you mean cmd.exe /C "cd %HOMEDRIVE%%HOMEPATH%\Desktop & Discord"?

Related

How to run a batch file with arguments in administrator mode from JavaSwing button using process builder?

I am creating a Java Swing application where I am taking input from user which will be used as arguments for a batch file.
After pressing a button, my batch file should get launched in ADMIN mode along with the arguments provided by user.
This is the command line:
powershell Start-Process -Verb runas cmd '/k System.getProperty("user.dir") + batchFilePath +arg1+ "" +arg2 + "" +arg3'
This command is working properly when we paste it in CMD window.
But I want code for a Java application so that we can run it from JButton.
So I used ArrayList and given this ArrayList as input to ProcessBuilder but I am getting an error.
code:
String launchCMD= System.getProperty("user.dir") + batchFilePath +arg1+ "" +arg2 + "" +arg3
final ArrayList<String> commands = new ArrayList<String>();
commands.add("powershell Start-Process -Verb runas cmd \'/k ")
commands.add(launchCMD)
commands.add("\'" );
ProcessBuilder pr=new ProcessBuilder(commands);
pr.start();
error:
java.io.IOException: Cannot run program ... : CreateProcess error=2, The system cannot find the file specified
Your question is not really related to Swing, it is related to how to use class ProcessBuilder and that class is not a terminal emulator. It does not parse a command line that you enter into a PowerShell window. You need to split the command into tokens. That's why the ProcessBuilder constructor takes a list of strings. Note that the parameters to ProcessBuilder constructor do not have to be string literals. You can create a string any way you like and pass it as an argument to the ProcessBuilder constructor.
You didn't post a sample batch file so I wrote one of my own, named showargs.bat which simply echoes its first argument.
#echo off
echo %1
The command that worked for me (i.e. ran the batch file as administrator) was:
powershell.exe -Command Start-Process cmd.exe -ArgumentList '/k C:\Users\USER\showargs.bat Diego' -Verb RunAs
Java code that executes the above command using class ProcessBuilder:
ProcessBuilder pb = new ProcessBuilder("powershell.exe",
"-Command",
"Start-Process",
"cmd.exe",
"-ArgumentList",
"'/k C:\\Users\\USER\\showargs.bat Diego'",
"-Verb",
"RunAs");
try {
Process proc = pb.start();
int status = proc.waitFor();
System.out.println("status = " + status);
}
catch (InterruptedException | IOException x) {
x.printStackTrace();
}

Using Java's Runtime.getRuntime().exec I get error with some commands, success with others -- how can this be determined? [duplicate]

When I try to run Runtime.exec(String), certain commands work, while other commands are executed but fail or do different things than in my terminal. Here is a self-contained test case that demonstrates the effect:
public class ExecTest {
static void exec(String cmd) throws Exception {
Process p = Runtime.getRuntime().exec(cmd);
int i;
while( (i=p.getInputStream().read()) != -1) {
System.out.write(i);
}
while( (i=p.getErrorStream().read()) != -1) {
System.err.write(i);
}
}
public static void main(String[] args) throws Exception {
System.out.print("Runtime.exec: ");
String cmd = new java.util.Scanner(System.in).nextLine();
exec(cmd);
}
}
The example works great if I replace the command with echo hello world, but for other commands -- especially those involving filenames with spaces like here -- I get errors even though the command is clearly being executed:
myshell$ javac ExecTest.java && java ExecTest
Runtime.exec: ls -l 'My File.txt'
ls: cannot access 'My: No such file or directory
ls: cannot access File.txt': No such file or directory
meanwhile, copy-pasting to my shell:
myshell$ ls -l 'My File.txt'
-rw-r--r-- 1 me me 4 Aug 2 11:44 My File.txt
Why is there a difference? When does it work and when does it fail? How do I make it work for all commands?
Why do some commands fail?
This happens because the command passed to Runtime.exec(String) is not executed in a shell. The shell performs a lot of common support services for programs, and when the shell is not around to do them, the command will fail.
When do commands fail?
A command will fail whenever it depends on a shell features. The shell does a lot of common, useful things we don't normally think about:
The shell splits correctly on quotes and spaces
This makes sure the filename in "My File.txt" remains a single argument.
Runtime.exec(String) naively splits on spaces and would pass this as two separate filenames. This obviously fails.
The shell expands globs/wildcards
When you run ls *.doc, the shell rewrites it into ls letter.doc notes.doc.
Runtime.exec(String) doesn't, it just passes them as arguments.
ls has no idea what * is, so the command fails.
The shell manages pipes and redirections.
When you run ls mydir > output.txt, the shell opens "output.txt" for command output and removes it from the command line, giving ls mydir.
Runtime.exec(String) doesn't. It just passes them as arguments.
ls has no idea what > means, so the command fails.
The shell expands variables and commands
When you run ls "$HOME" or ls "$(pwd)", the shell rewrites it into ls /home/myuser.
Runtime.exec(String) doesn't, it just passes them as arguments.
ls has no idea what $ means, so the command fails.
What can you do instead?
There are two ways to execute arbitrarily complex commands:
Simple and sloppy: delegate to a shell.
You can just use Runtime.exec(String[]) (note the array parameter) and pass your command directly to a shell that can do all the heavy lifting:
// Simple, sloppy fix. May have security and robustness implications
String myFile = "some filename.txt";
String myCommand = "cp -R '" + myFile + "' $HOME 2> errorlog";
Runtime.getRuntime().exec(new String[] { "bash", "-c", myCommand });
Secure and robust: take on the responsibilities of the shell.
This is not a fix that can be mechanically applied, but requires an understanding the Unix execution model, what shells do, and how you can do the same. However, you can get a solid, secure and robust solution by taking the shell out of the picture. This is facilitated by ProcessBuilder.
The command from the previous example that requires someone to handle 1. quotes, 2. variables, and 3. redirections, can be written as:
String myFile = "some filename.txt";
ProcessBuilder builder = new ProcessBuilder(
"cp", "-R", myFile, // We handle word splitting
System.getenv("HOME")); // We handle variables
builder.redirectError( // We set up redirections
ProcessBuilder.Redirect.to(new File("errorlog")));
builder.start();

Java execute debian terminal command with "|"

I am experiencing a really confusing issue about sending commands to terminal via Java.
I have exactly this code:
Process p = Runtime.getRuntime().exec(new String[]{"useradd", server, "-p", pass, "-d", "/home/dakadocp/servers/" + server, "-s", "/bin/false"});
Runtime.getRuntime().exec(new String[]{"echo", server + ":" + pass, "|", "chpasswd"});
The first command is this one "useradd user -p password -d /home/ftp/test/ -s /bin/false" and the second one should be this echo username:new_password | chpasswd, the first command works without any problem and creates the user which I define by the "server" variable, but when I try to execute the second command to change users pass this command probably never happen, output is null and the password is not changed, but when I type this command directly to the terminal it works perfectly so this is just Java issue.
I think the problem is in the character "|", before I tried also some command with "|" and its behavior was the same as with this command. What I am doing wrongly ?
Thanks.
Welite.
| is a shell feature, and requires a shell to run. The trivial fix is to run a shell:
Runtime.getRuntime().exec(new String[] { "sh", "-c", "echo something | chpasswd" });
However, java is more than capable of writing to a process with needing a shell or echo. The better way is to just run chpasswd by itself and writing the string to it:
Process p = Runtime.getRuntime().exec(new String[] { "chpasswd" });
PrintWriter writer = new PrintWriter(p.getOutputStream());
writer.println("foo:bar");
writer.close();

commandline call from java

I'm looking to call the command line from a java program. I have successfully entered the command line using this bit of code
String[] cmd = new String[2];
cmd[0] = "cmd /c dir";
Runtime rt = Runtime.getRuntime();
System.out.println("Execing " + cmd[0]);
Process proc = rt.exec(cmd[0]);
However, the actual commands aren't working. I am not too familiar with command line, I have only ever typed directly into it. So my question is how do I pass multiple arguments in? For instance if I wanted to change to C:\ I would have thought I could just add cd\ on the end but this doesn't seem to work?
Thanks in advance
use the & symbol. Everything needs to go in at once. For instance: cd .. & echo "test" will go to the previous directory and then echo test.
Taken from here: http://forums.techguy.org/dos-other/697113-solved-multiple-commands-cmd.html

Passing a string to the Windows command line

Please see the code below
Runtime rt = Runtime.getRuntime();
rt.exec("cmd /c start");
String[] cmd = {"LogParser", "Select top 10 * into c:\temp\test9.csv from application" };
rt.exec(cmd);
It opens the command window but the strings are not passed in after opening. Can someone tell me why this code won't place the strings into the command window?
The option /C means: Carries out the command specified by the string and then terminates.
So the other command is handled as a separated one.
Use OutputStreamWriter and write to the input stream of the process created.
Process p = Runtime.getRuntime().exec("cmd /K start") ;
Writer w = new java.io.OutputStreamWriter(p.getOutputStream());
w.append(yourCommandHere);
Also, the reason for using /K :
/K Run Command and then return to the CMD prompt.
Reference : http://ss64.com/nt/cmd.html
Why not use this:
String[] cmd = { "cmd /c", "LogParser",
"Select top 10 * into c:\temp\test9.csv from application" };
rt.exec(cmd);
Find more info about the exec method here.
You'll first need to start a process as you do in your first two lines of code, but don't use start because that spawns a separate process and returns immediately. Use just LogParser instead, or whatever will make your LogParser process start without involving cmd. After that you need to retrieve the OutputStream of the Process object created by exec and write your select command into it. You will also need to read from the Processs InputStream to see the response. None of this will be visible in a separate command-prompt window; you'll need to process everything through Java and it will involve some multithreading as well.
As I said in my comment - 'They are executed as separate commands, they are not related just because you executed one before the other'
From the Runtime.exec( string ) javadoc -
Executes the specified command and arguments in a separate process.
You need to chain the commands together to get cmd to process your command, I believe you need to use the \k flag to specify what commands you need executed on the command line.
Runtime rt = Runtime.getRuntime();
String start = "cmd /k ";
String cmd = "LogParser;\n" Select top 10 * into c:\temp\test9.csv from application";
rt.exec(start + cmd);
Not tested as I don't have windows, but it should be similar to this.

Categories