Process.start() odd behavior - java

I am trying to use code to run a popular bitcoin miner.
https://dl.dropboxusercontent.com/u/92716895/DiabloMiner.zip
If you guys know if it, it might be helpful. The thing is that it is a java bitcoin miner. Which needs some dlls to run. The way I manually run it works... which is via cmd going into the directory and typing,
DiabloMiner-Windows.exe -u user -p pass -o server
But when I use the below code to do the same it doesn't work it gives me cannot locate java library path lwjgl.
diabloMinerExe = Path.Combine(storageLocation, "DiabloMiner", "DiabloMiner-Windows.exe");
miner = new Process();
miner.StartInfo.FileName = diabloMinerExe;
miner.StartInfo.Arguments = "-u " + this.user + " -p " + this.password + " -o " + this.server;
miner.Start();
To clarify...
" It's a C# Project that starts a Process which is a .exe which starts a Java based bitcoin miner. "

System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = "cmd.exe";
startInfo.Arguments = "/K java -cp libs\\*;DiabloMiner.jar -Djava.library.path=libs\\natives com.diablominer.DiabloMiner.DiabloMiner -u youruser -p yourpassword -o server";
process.StartInfo = startInfo;
process.Start();
This is a working example... I've made it run. If you need help with it, give me a shout ;)
You will need libs folder and DiabloMiner.jar in the directory of your C# app

Related

how to execute a command with it's native gui using process builder

if(os.contains("windows"))
{
File bat = new File(System.getenv("APPDATA") + "/SelfCommandPrompt", appId + "-run.bat");
bat.getParentFile().mkdirs();
List<String> list = new ArrayList(1);
list.add("#echo off");
list.add("start" + " \"" + appName + "\" " + command);
IOUtils.saveFileLines(list, bat, true);
ProcessBuilder pb = new ProcessBuilder(bat.getAbsolutePath());
//inherit IO and main directory
pb.directory(getProgramDir());
//fire the batch file
pb.start();
System.exit(0);
}
So I dynamically create a .bat file and I want to run the process but, NOT IN THE BACKGROUND. Java forces the process to happen in the background how do I make it so it's not in the background? I am not looking to get the output stream from the .bat file I only want to execute it with the native gui it's intended to use on double click. Everywhere I look on these forums it only tells me how to do it in the background and get the outputstream? Why isn't there a boolean for this in the process builder? For my program specifically right now I want to reboot my java program with command prompt terminal on double click. I have the command generation working I tested the .bat file but, java again forces it to happen in the background.
Another use for doing a process not in the background. A java launcher for a game which executes a program with the gui not in the background which I may also need in the future.
Also the bat files output which is dynamically generated based off of the enviorment
java -Dfile.encoding=Cp1252 -cp C:\Users\jredfox\Documents\MDK\md5-spreadsheet\filededuper\bin;C:\Users\jredfox\Documents\MDK\md5-spreadsheet\filededuper\libs\apache-codecs.jar jredfox.selfcmd.SelfCommandPrompt true jredfox.filededuper.Main
edit I figured out a command for windows but, only windows. I need commands for mac
Runtime.getRuntime().exec("cmd /c start" + " \"" + appName + "\" " + command);
Figured it out.
basically get the terminal string on linux you need to make an api for it
save any shell scripts you need in the appdata
make an api to get the app data folder
create your custom command
return if conditions are not met like the System.console != null for my thing yours will be different.
execute command in new terminal window therefore the new native terminal using os commands.
All the code is found here.
https://github.com/jredfox/OpenTerminal

How do you run a ffmpeg command in Java, in MacOS, using a ProcessBuilder

I am writing a program in Java that uses ffmpeg to "snip" a video into several pieces and the stitch them back together again. I have everything working relatively smoothly in Windows, but I cannot get ffmpeg to work in Mac, or in Linux for that matter. I'm focusing on mac right now though. I thought that it might be a permissions problem, but when I run it with sudo I get an error that says (after typing in the password:
sudo: ffmpeg: command not found
when I run it without sudo I get:
java.io.IOException: Cannot run program "ffmpeg": error=2, No such file or directory
I think that it might be because the ffmpeg package, on the Mac machine, was downloaded with homebrew, and ffmpeg is stored in /usr/local/Cellar/ffmpeg instead of the default folder, wherever it may be. That may not be the problem though, because I deleted ffmpeg and re-downloaded it with homebrew. It may have been in its defaulter folder in my first tests as well. It would be great to figure this out. Most of my family uses Mac (not me) and I really want to share my work with them. That is why I chose to code this in Java. Oh, and I did try using the directory to the binary in the command. Here's the code:
//snips out all the clips from the main video
public void snip() throws IOException, InterruptedException {
for(int i = 0; i < snippets.size(); i++) {
//ffmpeg -i 20sec.mp4 -ss 0:0:1 -to 0:0:5 -c copy foobar.mp4
String newFile = "foobar" + String.valueOf(i) + ".mp4";
//THIS WORKS
if(OS.isWindows()) {
ProcessBuilder processBuilder = new ProcessBuilder("ffmpeg", "-i", videoName, "-ss",
snippets.get(i).getStartTime(), "-to", snippets.get(i).getEndTime(), newFile);
Process process = processBuilder.inheritIO().start();
process.waitFor();
System.out.println("Win Snip " + i + "\n");
}
else if (OS.isMac()) {
//FFMPEG LOCATION: /usr/local/Cellar/ffmpeg
//THE ERROR: sudo: ffmpeg: command not found
//ERROR W/OUT SUDO: java.io.IOException: Cannot run program "ffmpeg": error=2, No such file or directory
ProcessBuilder processBuilder = new ProcessBuilder("sudo", "-S", "ffmpeg", "-f", videoName, "-ss",
snippets.get(i).getStartTime(), "-to", snippets.get(i).getEndTime(), newFile);
Process process = processBuilder.inheritIO().start();
process.waitFor();
System.out.println("Mac Snip " + i + "\n");
}
else if (OS.isUnix()) {
System.out.println("Your operating system is not supported");
//TODO
//need to figure out if deb/red hat/whatever are different
}
else if (OS.isSolaris()) {
System.out.println("Your operating system is not supported yet");
//TODO probably won't do
}
else {
System.out.println("Your operating system is not supported");
}
//add to the list of files to be concat later
filesToStitch.add(newFile);
filesToDelete.add(newFile);
}
//System.out.println(stitchFiles);
}
As Mac OS is UNIX-based, you need to put "./" before the executable name if the location isn't in the configured path (i.e. the $PATH environment variable). Changing "ffmpeg" to "./ffmpeg" should hopefully work (assuming that it is genuinely located in the working directory -- you can also change the working directory by calling directory() on your ProcessBuilder if necessary).
After listening to everyone telling me it was a problem with the filepath I decided to double check that I had the right directory. I didn't. I saw a "ffmpeg" file in the homebrew folder, but I found out that I could type:
type ffmpeg
into the terminal to find the filepath. It turns out it was actually under usr/local/bin/ffmpeg. All I had to do was add it to my code
ProcessBuilder processBuilder = new ProcessBuilder("usr/local/bin/ffmpeg", "-f", videoName, "-ss", snippets.get(i).getStartTime(), "-to", snippets.get(i).getEndTime(), newFile);
I feel like a complete moron.

Java command through CMD not working in C#.NET

I'm trying to run a java command in cmd using C# to get some inputs for my program, the path for Java is set correctly, and I am able to run Java commands in the cmd without any trouble but when I tried it in C#, it's showing " 'java' is not recognized as an internal or external command, operable program or batch file. " as if the path is not set.
But I am able to run the same command outside, don't know what seems to be the issue, kindly help, thanks in advance!
string cmd = #"/c java -jar """ + $"{treeEditDistanceDataFolder}libs" + $#"\RTED_v1.1.jar"" -f ""{f1}"" ""{f2}"" -c 1 1 1 -s heavy --switch -m";
Console.WriteLine(cmd);
var proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = cmd;
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.Start();
Console.WriteLine("Process started");
string output = proc.StandardOutput.ReadToEnd();
Console.WriteLine("Output was read");
string error = proc.StandardError.ReadToEnd();
proc.WaitForExit();
This line is your problem:
proc.StartInfo.UseShellExecute = false;
When UseShellExecute is true, the system and user PATH variables will be used if the application to launch is just the executable name. Because you're setting it to false, and java doesn't exist in your application's folder, it isn't possible for .NET to find it.
You have two options:
Set UseShellExecute to true so that it can use the PATH variable to find java.
Use a fully qualified path, e.g. "C:\Program Files\Java\jdk1.8.0_101\bin\java"
See this answer for more info.

Run SQL script on PostgreSQL with password supplied

I'm trying to run an SQL-script from within my Java app. This is my code:
Runtime rt = Runtime.getRuntime();
rt.exec("setx PGPASSWORD \"" + password + "\"");
String command = String.format("psql -d %s -h %s -p %s -U %s -w -f %s",
database, host, port, user, "create_tables.sql");
System.out.println("Executing command " + command);
Process p = rt.exec(String.format(command));
p.waitFor();
This prints
psql -d routes -h localhost -p 5432 -U postgres -w -f create_tables.sql
as expected.
However within my databases log I see the following:
psql: fe_sendauth: no password supplied
How do I supply the password to psql when calling it as process?
Your environment variable should be set in the same process as the psql is executed. This does not happen in your code as you execute two different processes.
The thing is, that environment variables are local to process contexts.
A new process gets a copy of the parent's environment but each copy is independent.
In your case, the Java process creates child process that modifies PGPASSWORD through setx command - so far so good.
However, this doesn't affect the Java process. Your second child process isn't running in a shell, so it ignores the PGPASSWORD variable as the process is created using OS services. Those services, take into consideration the old context of the Java process which is not aware of PGPASSWORD unless you change the environment in the shell before you start the original (parent) Java process.
Thus,to solve your problem, you have to set up the environment variable and then run the child as a shell command (cmd /c).
To set up environment variable we could follow #Little Santi's advice.
So the code would look something like the following
Runtime rt = Runtime.getRuntime();
String setCommand="PGPASSWORD=" + password;
String command = String.format("psql -d %s -h %s -p %s -U %s -w -f %s",
database, host, port, user, "create_tables.sql");
String finalCommand = "cmd /c \" " + command +"\"";
System.out.println("Executing command " + finalCommand);
Process p = rt.exec(finalCommand ,new String[]{setCommand});
p.waitFor();
Edit 2:
#Plirkee's diagnosis is right: The process in which you start psql misses the required environment variable. But to set it on properly it's better to use the Runtime.exec(String[] cmdarray, String[] envp) method.

Issue starting cmd.exe twice in a row

I am trying to automate some processes that were build in ancient times, for the sake of avoiding repetitive actions. It is required that the processes are started with one batch and stopped with another (this can not be changed btw).
So i made a commandline tool to do this (and many other repetitive stuff) and I have modelled a command that starts the 'startbatch' and a command that start the 'stopbatch'. Both commands work fine separatly (as I tested them separatly) but there seems to be a problem when i want execute them one after another (in the correct order ofcourse). I get the following error in new cmd.exe window:
The process cannot access the file because it is being used by another process.
the code that i am using to start the batches looks like this:
public void startBatchInDev(String company){
String startBatchFolder = locations.getLocationFor("startbatch");
try{
Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd.exe /C cd \"" + startBatchFolder + "\" & start cmd.exe /k \"" + BATCHSTART + company.toLowerCase()+ "-dev" + BATCH_SUFFIX + "\"");
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
public void stopBatchInDev(String company){
String startBatchFolder = locations.getLocationFor("startbatch");
try{
Runtime runtime = Runtime.getRuntime();
runtime.exec("cmd.exe /C cd \"" + startBatchFolder + "\" & start cmd.exe /k \"" + BATCHSTOP + company.toLowerCase()+ "-dev" + BATCH_SUFFIX + "\"");
}
catch(IOException ioe){
ioe.printStackTrace();
}
}
The names of the batchfiles are concatenated, but they are OK once the application is running.
The error message is quite clear, some file is locked and I can't access it because of it. Some googling confirms my suspicion, but I can't seem to find a solution for this. The hits in google are all about obvious uses of files, like an obvious shared resource. But in my case, i am not working on the same batch file. The stop and start batch are two different files. So I am actually starting to think that it might be the cmd.exe file that is being locked by windows...
So this question is actually two questions:
- what is the exact cause of the described problem?
- how do i programmatically fix this (if possible)?
thanks in advance!
So, basically, bat is not so great :-(
I was able to repro this from java, but I also found that this script:
#echo off
echo STOP
echo STOP >> E:\tmp\java\logfile.txt
C:\cygwin\bin\sleep.exe 1
echo STOP1 >> E:\tmp\java\logfile.txt
C:\cygwin\bin\sleep.exe 1
echo STOP2 >> E:\tmp\java\logfile.txt
When run twice like this:
start test.bat && start test.bat
Will fail with one or more messages like:
The process cannot access the file because it is being used by another process.
The reason is that " >> " redirection opens the file for Read/Write access but only FILE_SHARE_READ sharing. If two different programs attempt to open the file this way, one of them fails.
So, you cannot have two different batch files running at the same time and logging to the same file

Categories