Powershell process hanging when called from Java application - java

I am trying to write a simple application that takes in a command line arguement (which will be a Powershell ps1 file) and then run it. So I have experemented with a number of different approaches and seem to be running into a problem. If I attempt to invoke powershell from within java, the windows process is started and is visible via process explorer, however powershell never returns, it hangs in some sort of loop by the looks of it. The command I am using is:
String command = "powershell -noprofile -noninteractive \"&C:\\new\\tst.ps1\"";
The command is then executed using:
Runtime systemRuntime = Runtime.getRuntime();
Process proc = systemRuntime.exec(command);
At the moment I am hard coding the location to the ps1 file as I was trying to rule this out as an issue. Using a process explorer I can see the hanging powershell process and the command that was passed to it was :
powershell -noprofile -noninteractive "&C:\new\tst.ps1"
which when copied into a cmd window, works to launch the tst.ps1 file. The file itself is incredibly simple in this example and I think I can rule it out being the cause of the freeze as I have tried to launch other ps1 files the same behaviour can be seen.
To further add to the confusion, if I use the java code posted above and pass in powershell commands instead of a file name then it successfully runs.
I've scoured the web and see lots of people experiencing the same issue but no one seems to have posted there solution, I hope its a simple oversight on my part and can be easily fixed.
Any hints/tips are appreciated :D
Alan

You have to close OutputStream in order for Powershell to exit.
Runtime systemRuntime = Runtime.getRuntime();
Process proc = systemRuntime.exec(command);
proc.getOutputStream().close();

Is your external program writing to the standard outputs (err and out)?
If yes, it can hang waiting for you to consume them from the java parent process.
You can get those as InputStreams by calling
Process.getInputStream()
and
Process.getErrorStream()
There's more details here:
Javadoc for Process

Related

Execuring powershell commands from Java

I am trying to execute powershell commands from Java and have tried multiple options.
Commands that I want to try -
$SecureFilePassword = ConvertTo-SecureString -String "<PFXPassword>" -AsPlainText -Force
$userPFXObject = New-IntuneUserPfxCertificate -PathToPfxFile "<FullPathPFXToCert>" -PfxPassword $SecureFilePassword -UPN "<UserUPN>" -ProviderName "<ProviderName>" -KeyName "<KeyName>" -IntendedPurpose "<IntendedPurpose>"
I tried using ProcessBuilder to execute these - but i am not able to maintain session and hence it starts saying cmdlet not known even after importing the corresponding ps1 file.
Then I started with using jPowershell - here everything works fine except the above commands when it tries to use the set value inside $SecureFilePassword inside the next command - it fails saying "Not Specified"
Not sure if I am formulating the command properly to be executed - could some one help me?
Thanks
Sri
I would suggest to write a PowerShell script in a file that could be run in your shell as a single command and after that use ProcessBuilder.start() or Runtime.exec() method to run an external command from Java. See class Process API for details

Backup MySQL via Java

I am making a program to automatically backup a MySQL database from within java using MysqlDump. I want to get the file created and zip it. However, I am having an issue with the MySQLDump.
I am using the following to create a MySQLDump:
Process pr = Runtime.getRuntime().exec(
"mysqldump -u "+user+" --password='"+password+"' "+database+" > /root/moltres/backups/sql/"+database+".sql"
);
I have a while loop after this which remains in the loop if pr.isAlive(). I thought this would work, but it appears that when the command is executed, the process instantly becomes no longer alive. I could make the thread sleep, but for how long? How can I make the same SQL backup, but detect when the mysqldump command has completed?
The command is exiting immediately all right. It is failing, because the redirection isn't being understood by mysqldump.
This is not how you use Process. You need to:
Use ProcessBuilder.
Merge the output and error streams.
Add sh -c or cmd /c as appropriate to the beginning of the command line to handle the redirection.
Start the process.
Consume the output stream and log it, reading until end of stream.
Call Process.waitFor().
Get the process's exit code and log that.
Why you're using Java for this at all is a mystery. It's just a shell script. Indeed you can get MySQL to schedule its own backups automatically, without even needing a script.

How to run linux script from Java

I want to run linux script from Java program and continue to execute program only when script stop. I am not interested to read script output ... Can anybody help me?
Thanks a lot,
and excuse me for my bad English
Assuming all other threads are idle:
// run the script.
Process proc = Runtime.getRuntime().exec("/path/to/myscript");
// wait for the return code.
int ecode = proc.waitFor();
If you have more complex arguments to your script, or it needs to monitor STDOUT, STDERR, or needs other modifications (like feeding data to STDIN, or changing execution directory, environment variables, etc.) then you should do the same effective procedure, but instead of using Runtime.exec(...) you should build and start the Process manually. Read the Process javadoc and ProcessBuilder javadoc on how to set it up, and start it.
You can also launch the bash interpreter instead
Process proc = Runtime.getRuntime().exec("/bin/bash /path/to/myscript");
int ecode = proc.waitFor();
This may work in some generally broken cases when #rolfl solution may not work (non executable script file, #!/ header missing, etc)

Netbeans project still running when using `Runtime.getRuntime().exec("explorer.exe");`

I'm working on a (non-malicious) screen-locking sort of Swing application, and I've adapted code from Martijn Courteaux's answer at Use Java to lock a screen to do this. The problem is that when I use Runtime.getRuntime().exec("explorer.exe"); to reopen the Explorer process at program closing, Netbeans thinks that my project is still running because the resulting explorer.exe is running. CMD prompt and JCreator don't have this issue.
Can anyone give an example of the preferred way to call a command like explorer.exe to avoid this happening with Netbeans?
Edit: I close the Explorer process at the start of the program (which includes the taskbar). When I run Explorer, it's not to open a Windows Explorer window (which works totally fine with the given answers) but to restore the regular Windows UI.
The problem is Runtime#exec is waiting for the child process to exit. This is the default behavior.
If you want to execute a parentless process (a process in which the parent process can terminate even though the child is still running), you need to get a little more creative.
We use...
"cmd /C start /B /NORMAL " + yourCommand
I would highlight recommend using ProcessBuilder as it makes it significantly easier to build and execute external commands.
Something like...
ProcessBuilder pb = new ProcessBuilder("cmd", "/C", "start", "/B", "/NORMAL", "explorer.exe");
pb.start();
For example....
nb I run this is NetBeans and the program exited after/as explorer opened.
There is one little draw back. This doesn't like long file names. You'll need to find some way to produce short file names/paths for this to work. I was forced to use JNI solution for this
ProcessBuilder allows you to create and control processes.
Here's some example code, it's fairly complex but I don't have time to dumb it down (no offense): https://github.com/Xabster/Botster/blob/master/src/commands/ExecCommand.java

How can I run a bash script (which downloads a file) in Java?

Running in Mac OS X Lion, I need to retrieve a file from a remote server using a script in the command line. The command I'm trying to use in code is "bash /my/path/here/myscript" and I already run another process from the command line (atos) using the code below.
Process proc = Runtime.getRuntime().exec(cmd);
But while debugging, the program continues without error, yet the script does appear to have actually run. Furthermore, there should be a pause of several seconds while the script retrieves the file, yet my program continues to execute immediately. The script itself works as intended when run from the terminal. I'm a little stumped on how to get this to work, so any help would be greatly appreciated.
Got it to work with the following code -
Process proc = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
proc.waitFor();
while (in.ready()) {
System.out.println(in.readLine());
}
The other thing that was an issue is that the script would download to the current working directory rather than the location of the script itself (as intended). So the script would run correctly while my program would continue to fail to find the downloaded file. Hope this helps.

Categories