Problems With Spaces In Path In System.Diagnostics.Process parameters - java

First let me say that this question is not a duplicate of Use Process.Start with parameters AND spaces in path. I am using the System.Diagnostics.Process to start a cmd.exe window and then running java in that window. Except I want the java command to be run based on their installed Java path, as the PATH environment variable is unreliable and doesn't seem to get set very often when Java is installed. So I replaced the "java" in my arguments for the Process with the actual Java path, but now I'm getting this error:
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
Clearly this is because there are spaces in the name, but I am properly quoting the path and using escape characters to create those quotes. Here is the code used to run the cmd.exe:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
//startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = "cmd.exe";
if (chbPath.Checked) startInfo.Arguments = "/C \"" + javaPath + "\\bin\\java.exe\" -Djava.library.path=\"lib\\natives-win\" -jar SecondDimension.jar " + chbWindowed.Checked.ToString();
else startInfo.Arguments = "/C java -Djava.library.path=\"lib\\natives-win\" -jar SecondDimension.jar " + chbWindowed.Checked.ToString();
process.StartInfo = startInfo;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.Start();
this.Visible = false;
process.WaitForExit();
Console.WriteLine(process.StandardError.ReadToEnd());
Application.Exit();
If chbPath.Checked = false, it runs the command with the java command set with PATH. Which works fine for me, but doesn't for people who haven't ever tried to run java from the command line. But when I check chbPath, then I get the error listed above. Can anyone help with this? This is really annoying and I should have been done with this hours ago, but of course a SPACE....a SINGLE SPACE is stopping me from progressing....ARGHHH!!!
Edit:
Also here is the code for my path finder, which I pulled off another post here:
String javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment";
using (var baseKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64).OpenSubKey(javaKey))
{
String currentVersion = baseKey.GetValue("CurrentVersion").ToString();
using (var homeKey = baseKey.OpenSubKey(currentVersion))
return homeKey.GetValue("JavaHome").ToString();
}

First you could use the property ProcessStartInfo.WorkingDirectory to set the working folder for the Java process, then, because your program is in a different directory you need to change the path to this program.
You could set an Environment variable and use that variable to complete the path to the program or directly include the name of the program in the environment variable
Environment.SetEnvironmentVariable("JAVA_PRG", #"d:\temp"); // Whatever
Process process = new Process();
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.WorkingDirectory = Path.Combine(javaPath, "bin");
startInfo.FileName = "cmd.exe";
if (chbPath.Checked)
startInfo.Arguments = "/C java.exe .... -jar %JAVA_PRG%\SecondDimension.jar ";

Ok, so I was able to fix it. Apparently I don't need to run a cmd window to run the java command, because using diagnostics.process to start a progarm this way always creates a console window. So I just changed the GetJavaInstallationPath() code to return the path to the actual java executable, and then just set StartInfo.FileName = GetJavaInstallationPath(); which pretty much solved all my problems. This way the working directory stays in the game's directory and I still get the console window I wanted. So I guess I was trying too hard. :) Here's the fixed code:
private void btnLaunch_Click(object sender, EventArgs e)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = GetJavaInstallationPath();
startInfo.Arguments = "-Djava.library.path=\"lib\\natives-win\" -jar SecondDimension.jar " + chbWindowed.Checked.ToString();
process.StartInfo = startInfo;
process.Start();
this.Visible = false;
process.WaitForExit();
Application.Exit();
}

Related

start process from java when java run as service

I have a java process running as windows server using prcorun (http://commons.apache.org/proper/commons-daemon/); unfortunatly I have to launch an external legacy command written in C/C++.
both
Process myProcess = Runtime.getRuntime().exec(command);
and
Process myProcess = new ProcessBuilder(command, arg).start();
work well when java is launched as a stand-alone application, but when I start java as service it replies
command not found
also with
Process myProcess = Runtime.getRuntime().exec("dir");
command not found
I think is a problem due to windows services.
Any suggestion?
I would try to do a quick test and print the PATH environment variable in your service. What I usually found when you run some command as a service, the PATH might not be totally available (which can also explain why DIR is not working for you). If that the case, when starting the service, you have to make sure the PATH include both the normal bin and your legacy bin.
As the error says, the command is not found in the path. You'll need to set the environment variable PATH to the child process's environment. Look at exec(cmd, String[] env) method. You can create an array of environment variables (key value pairs) and pass it to exec().
In my case I used
cmd /c <<YOUR COMMAND>>
eg.
Process myProcess = Runtime.getRuntime().exec("cmd /c dir");
also I added the envinronments. as suggested by smurf
private static String[] getEnv() {
Map<String, String> env = System.getenv();
String[] envp = new String[env.size()];
int i = 0;
for (Map.Entry<String, String> e : env.entrySet()) {
envp[i++] = e.getKey() + "=" + e.getValue();
}
return envp;
}
...
Process myProcess = Runtime.getRuntime().exec("cmd /c dir",getEnv());
Alternative to java.lang.Runtime.exec() that can execute command lines as a single string?

Java.exe does not open with Process.start

I have an application that needs to be opened with Java.exe . when i try to open the application with Command prompt with the following arguments
C:\MyworkingFolder\>start java -MyParamters ->This works and the application is launched
But when i use the same in my c# code
var pInfo = new ProcessStartInfo
{
FileName = "Java",
WorkingDirectory = "MyworkingFolder",
Arguments = -MyParamters
};
Process monitorProcess = Process.Start(pInfo);
This code part does not work. All that i get is a window that shows OpenWith
The application now works fine.. I have given the full path for Java "C:\ProgramData\Oracle\Java\javapath\java.exe" and it works now.

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.

Installing Java with silent install into a directory with spaces

I am trying to install Java using the silent mode and also specify an installation directory that contains spaces. When I do this it pops up the "Windows Installer" dialog box indicating one of the parameters is incorrect. If I use the short path name it works correctly, but I really would prefer not to use the short directory name because that is the value that gets stored in the Registry.
The command I want to use...
jre-6u39-windows-i586.exe /s INSTALLDIR="C:\Program Files (x86)\Java"
This pops up the Windows Installer dialog box.
When I use...
jre-6u39-windows-i586.exe /s INSTALLDIR=C:\Progra~2\Java
This works.
NOTE: "Program Files (x86)" is just an example. This is installed at client sites and they choose the install directory, therefore we have to be able to support any directory they may specify.
Any idea how I can do a silent install but still use the long path name?
UPDATE:
I thought I would share the final solution. One cool thing I found that I wanted to share is that you can suppress the auto-reboot of install and it returns an exit code of 3010. Therefore you can defer the reboot to another time. Here is the code (rewritten a bit to eliminate a bunch of our own abstraction)
public bool InstallJava(string installPath, string logFile)
{
bool rebootRequired = false;
string fullLogFileName = Path.Combine(logFile, "JavaInstall.log");
string arguments = string.Format("/s /v\"/qn REBOOT=Suppress INSTALLDIR=\\\"{0}\\\" STATIC=1 /L \\\"{1}\\\"\"", installPath, fullLogFileName);
ProcessStartInfo startInfo = new ProcessStartInfo { RedirectStandardError = true, RedirectStandardOutput = true, RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true,
FileName = "jre-7u25-windows-x64.exe", Arguments = arguments };
var process = Process.Start(startInfo);
process.WaitForExit();
if (process.ExitCode == 3010)
rebootRequired = true;
else if (process.ExitCode != 0)
{
// This just looks through the list of error codes and returns the appropriate message
string expandedMessage = ExpandExitCode(StringResources.JAVA_INSTALL_ERROR, process.ExitCode, fullLogFileName);
throw new Exception(expandedMessage);
}
return rebootRequired;
}
i recall encountering this issue before....
You need to use quotes when passing paths to the installer if the
paths have spaces. Because the path arg is already in quotes, you
need to escape each quote with a '\' so it gets passed through. So
the command would be
j2re.exe /s /v"/qn INSTALLDIR=\"C:\Program Files\JRE\""
reference :
http://docs.oracle.com/javase/1.5.0/docs/guide/deployment/deployment-guide/silent.html
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4966488

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.

Categories

Resources