Java: showInputDialog and ProcessBuilder - java

I just started coding in Java and i'm trying to make a program to run chkdsk when i click on a JButton. I will put a bit of the code here so you guys can help me:
String disk = JOptionPane.showInputDialog(Janela, "Especifique a letra do disco (Exemplo: C:)", "CHKDSK /F", JOptionPane.QUESTION_MESSAGE);
if (disk.length() == 2 && disk.endsWith(":")) {
try {
String disk2 = ("fsutil dirty set " + disk)
ProcessBuilder chkdskf = new ProcessBuilder("cmd.exe", "/C", "start", disk2);
Process chkdskff = chkdskf.start();
}
catch (IOException fnfex2) {
System.out.println ("Erro no CHKDSK /F");
}
}
else {
JOptionPane.showMessageDialog(Janela, "Erro!", "Erro", JOptionPane.ERROR_MESSAGE);
}
So, it shows a InputDialog so you can put a drive letter (like C: or D:), and after that it checks if the string is the way i want. (Has two characters and ends with a ":"). Then, it starts a new cmd window with the command to make chkdsk run on the next reboot. However, it doesn't work. The CMD window that is opened when the code is executed has the title of "fsutil dirty set C:", but nothing happens, no command is executed. Any help is appreciated, and sorry for my poor english.

From the command line help for start
STATE ["title"] [/D path] ... [command/program] [parameters]
So, based on that, it would mean that start is taking fsutil dirty set C: as the title - the reason is because of the way the parameters work in ProcessBuilder.
Each element in the array is a separate argument been sent to the command, this is really helpful as it means you don't need to worry about quotes or other escaping requirements
So, based on all of this, you should construct your ProcessBuilder more like...
ProcessBuilder chkdskf = new ProcessBuilder("cmd.exe", "/C", "start", "Make it so", "fsutil", "dirty", "set", disk);

I don't know the way you are implemented. But I have an idea for your refer. Let's create a .bat file, write the execute statement to this file, then call to run this .bat file like this:
Runtime.getRuntime().exec("cmd /c start " + "command.bat");

Related

Java ProcessBuilder is not able to start GNU screen

I'm experiencing a weird behaviour of java's ProcessBuilder.
What I try is to stop a running screen using a shell, delete a few folders and after that restart the screen using another shell script.
The first step, killing the running screen, runs perfectly using:
ProcessBuilder pb0 = new ProcessBuilder(System.getProperty("user.dir") + "/generator/stop.sh");
In this stop.sh shell I simply run
screen -X -S generator kill
which works as it should.
After that I delete my directorys using org.apache.commons.io.FileUtils and then I want to start the screen again. Currently I'm doing it like that:
System.out.println("Restarting the generator");
ProcessBuilder pb1 = new ProcessBuilder();
pb1.directory(new File(System.getProperty("user.dir") + "/generator"));
pb1.command("./start.sh");
try {
Process process = pb1.start();
System.out.printf("Started the generator with %d", process.waitFor());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
This gives out "Started the generator with 1" which indicates to me that the screen runs which is simply not the case when checking with screen -ls.
No errors, no clue on how to move forward from here
Inside start.sh:
screen -S generator java -Xms2G -Xmx2G -jar generator.jar
PS: I'm using Debian 10.
Maybe anyone can help me out here?
Greets!
You should never ignore process output, because it's buffer has limited length, and if you don't consume it, it will hang. Im not sure if this is causing your issue, but this is definitely something you should do.
It is also possible that process throws some error that you can't see because you are ignoring it's output (in which case, this will help you to investigate the issue).
Try this:
new ProcessBuilder()
.redirectOutput(ProcessBuilder.Redirect.INHERIT)
.redirectError(ProcessBuilder.Redirect.INHERIT)
...
This will redirect process output stream and input stream to it's parent (which is your application).

Make a Java application run itself from the command prompt?

I have an executable Jar file and to keep it simple, I want to make it so that you can simply double click it on the desktop and it will run. I've tried this:
if(args.length == 0){
String path = Main.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String decodedPath = URLDecoder.decode(path, "UTF-8");
Runtime rt = Runtime.getRuntime();
Process pr = rt.exec("java -jar \"" + decodedPath + "\" -arg");
System.out.println("java -jar \"" + decodedPath + "\" -arg");
}
To no avail. I assumed that if I told the program to check for the "-arg" argument and it wasn't there, then it would asssume the program was run from the executable, not being called from the command line. So is there a way to make the program open a command prompt and then run itself within it, killing the previous program?
As to "run on double click", this is OS dependent.
You can "run a jar" at the command line using:
java -jar the.jar
This requires that the jar has a META-INF/MANIFEST.MF and that this manifest file has a Main-Class entry, the argument being the class where your main() method is. For instance:
Main-Class: org.foobar.mypackage.Foo
What I have done for a similar problem is that I have made a separate GUI program in a JAR file with some JTextFields for input and a JButton for confirmation. When the button gets clicked, it calls the main method in my other class with those values in a String array to start that program and close the GUI form with frame.setVisible(false). I suggest doing something like that, but it's dependent on what type of program you're developing.
You could also just pass the necessary command-line flags directly into the JRE at runtime! I just figured this out a couple weeks ago, but you can access the java.library.path and change it to match necessary library paths through reflection by just putting this code in the front of your main method.
try{
System.setProperty("java.library.path", path);
Field fieldSysPath = ClassLoader.class.getDeclaredField( "sys_paths" );
fieldSysPath.setAccessible( true );
fieldSysPath.set( null, null );
}catch(Exception ex){
// just exit and tell user that there was an error or something similar
}
Anyway, I hope that this was helpful. You can also do many similar things by similar code.

Command prompt doesn't open with Runtime.getRuntime().exec

I've created a GUI (swing) that executes a batch file that contains a command prompt .exe file execution with specific parameters.
When I run the batch file manually (by double clicking it), everything is as expected.
The problem is: the command prompt window doesn't open to show progress, moreover, it doesn't really start to work (only initiated) until I exit the GUI (forking?). When it starts to work, is works somewhere in the background and seen only in the task manager.
Only a blank command prompt window is opened.
From digging little bit around, I've constructed this command that gives me same result as above:
Runtime.getRuntime().exec("cmd.exe /c start \"Encoding\" cmd.exe /c start md \"" + Gui.outputDirField.getText() + "\\encoderOutput\" & cd \"" + Gui.outputDirField.getText() + "\\encoderOutput\" & \"" + Gui._batFile + "\" & pause");
Could you please assist?
Sorry if it sounds stupid..
this way works for me:
new Thread() {
#Override public void run() {
try {
Runtime.getRuntime().exec("cmd.exe /c start " + Gui._batFile);
} catch (IOException e1) {
e1.printStackTrace();
}
}
}.run();
trashgod may be on to something. We ran into issues with paths with spaces. This is from the release notes for jre 7u21
Changes to Runtime.exec
On Windows platform, the decoding of command strings specified to Runtime.exec(String), Runtime.exec(String,String[]) and Runtime.exec(String,String[],File) methods, has been improved to follow the specification more closely. This may cause problems for applications that are using one or more of these methods with commands that contain spaces in the program name, or are invoking these methods with commands that are not quoted correctly.
For example, Runtime.getRuntime().exec("C:\\My Programs\\foo.exe bar") is an attempt to launch the program "C:\\My" with the arguments "Programs\\foo.exe" and "bar". This command is likely to fail with an exception to indicate "C:\My" cannot be found.
The example Runtime.getRuntime().exec("\"C:\\My Programs\\foo.exe\" bar") is an attempt to launch the program "\"C:\\My". This command will fail with an exception to indicate the program has an embedded quote.
Applications that need to launch programs with spaces in the program name should consider using the variants of Runtime.exec that allow the command and arguments to be specified in an array.
Alternatively, the preferred way to create operating systems processes since JDK 5.0 is using java.lang.ProcessBuilder. The ProcessBuilder class has a much more complete API for setting the environment, working directory and redirecting streams for the process.
Does your bat file requiere user interaction or why are you putting a pause on your command? If so, the Runtime.exec just runs the file with no window, why would you want a Window? >ou can get a Process object as a result from the exec, from this object you can get an InputStream (and if needed, an OutputStream) so you can print your output or interact with the process.

Running UNIX Source command in Java

This is my first question on stackoverflow so I'll try to keep it concise and relevant.
I'm currently creating a Java program that is attempting to call an external program located on the system, in order to do this however I am required to call a shell script that sets up links to the relevant libraries to ensure that the system is linked to these before the external program can be executed.
The issue at hand is that I cannot invoke the shell script through Java, I've researched high and low and am aware that of alternative ways such as the use of the ProcessBuilder class. Unfortunately I'm quite new to the world of trying to invoke command line statements through Java and so I'm stuck for answers.
An example of the code I am using can be found below:
private void analyse_JButtonActionPerformed(java.awt.event.ActionEvent evt) {
// Get project path for copying of Fortran program to folder and execution
String projectPath = Newproject_GUI.getProjectPath();
String sourcePath [] = {"/bin/sh ", "-c ","source ~/set_env_WRF_gnu.sh"} ;
Runtime fortranAnalyser = Runtime.getRuntime();
try {
Process p = fortranAnalyser.exec("cp main.exe " + projectPath);
Process k = fortranAnalyser.exec(sourcePath);
BufferedReader is = new BufferedReader(new InputStreamReader(k.getInputStream()));
String line;
while ((line = is.readLine()) != null) {
System.out.println(line);
}
} catch (IOException ex) {
Logger.getLogger(Analyser_GUI.class.getName()).log(Level.SEVERE, null, ex);
}
}
Process p works fine and does indeed copy main.exe to the intended directory when the method is called. Process k however does not and this is where the issue is.
Thanks in advance.
The issue is "source" is internal command of BASH (you are using "sh" but that is just BASH in the simplified mode). So what you do is:
you spawn new process "sh" and source something there (setting some VARIABLES I guess)
the process ends and all VARIABLES are lost
you spawn another process, but VARIABLES are already gone
I am not sure if you use those variables later on, but according to the script name it is probably setting some. Don't do that like this.
By the way if you only want to execute script in bash, you don't need to source it. To get it's side effects, just execute it with:
String sourcePath [] = {"/bin/sh ", "/home/XYZ/set_env_WRF_gnu.sh"} ;
Please note you cannot use ~ in this case, use Java to get your home dir.

Execute Unix system command from JAVA problem

I am facing a weird issue with executing a system command from JAVA code.
Actually i want to get the Mac OSX system information from my JAVA App.
For that im using
Runtime.getRuntime().exec("system_profiler -detailLevel full");
This is working fine.If i print the output,it is cool.
But i want to write this information to a plist file for future use.For that im using the -xml argument of system_profiler.like,
String cmd = "system_profiler -detailLevel full -xml > "+System.getProperty( "user.home" )+"/sysinfo.plist";
Process p = Runtime.getRuntime().exec(cmd);
Basically this should create a plist file in the current users home directory.
But this seems to be not writing anything to file.
Am i missing something here ?
My Java is more than rusty, so please be gentle. ;-)
Runtime.exec() does not automatically use the shell to execute the command you passed, so the IO redirection is not doing anything.
If you just use:
"/bin/sh -c system_profiler -detailLevel full > path/file.plist"
Then the string will be tokenized into:
{ "/bin/sh", "-c", "system_profiler", "-detailLevel", "full", ">", "path/file.plist" }
Which also wouldn't work, because -c only expects a single argument.
Try this instead:
String[] cmd = { "/bin/sh", "-c", "system_profiler -detailLevel full > path/file.plist" };
Process p = Runtime.getRuntime.exec(cmd);
Of course, you could also just read the output of your Process instance using Process.getInputStream() and write that into the file you want; thus skip the shell, IO redirection, etc. altogether.
Christian.K is absolutely correct. Here is a complete example:
public class Hello {
static public void main (String[] args) {
try {
String[] cmds = {
"/bin/sh", "-c", "ls -l *.java | tee tmp.out"};
Process p = Runtime.getRuntime().exec (cmds);
p.waitFor ();
System.out.println ("Done.");
}
catch (Exception e) {
System.out.println ("Err: " + e.getMessage());
}
}
}
If you weren't using a pipe (|) or redirect (>), then you'd be OK with String cmd = "ls -l *.java", as in your original command.
If you actually wanted to see any of the output in your Java console window, then you'd ALSO need to call Process.getInputStream().
Here's a good link:
Running system commands in Java applications

Categories

Resources