views:

57

answers:

2

I'm trying to dynamically run a .jar from a C# assembly (using Process.Start(info)). Now, from a console application I am able to just run:

ProcessStartInfo info = new ProcessStartInfo("java", "-jar somerandom.jar");

In an assembly, however, I keep getting a Win32Exception of "The system cannot find the file specified" and have to change the line to the full path of Java like so:

ProcessStartInfo info = new ProcessStartInfo("C:\\Program Files\\Java\\jre6\\bin\\java.exe", "-jar somerandom.jar");

This obviously won't do. I need a way to dynamically (but declaratively) determine the installed location of Java.

I started thinking of looking to the registry, but when I got there I noticed that there were specific keys for the versions and that they could not even be guaranteed to be numeric (e.g. "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.6" and "HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment\1.6.0_20").

What would be the most reliable "long-haul" solution to finding the most up-to-date java.exe path from a C# application?

Thanks much in advance.

- EDIT -

Thanks to a combination of GenericTypeTea's and Stephen Cleary's answers, I have solved the issue with the following:

private String GetJavaInstallationPath()
{
    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();
    }
}
A: 

As far as I know the idea is that the latest version of Java installed on the system is the first one found in the PATH environment variable, so you shouldn't need to look for any registry keys, just run the thing.

Try:

ProcessStartInfo info = new ProcessStartInfo("java.exe", "-jar somerandom.jar");

If it doesn't work make sure java.exe is in your path and let me know.

Grzenio
Unfortunately, no. If I check the `info.EnvironmentVariables["path"]`, it does not contain Java. On the other hand, if I just open a command prompt, I can just `> java -jar somerandom.jar` all day, so I know it's supposed to be there.
Lance May
Could you check which java.exe process runs when you run it from command prompt?
Grzenio
@LanceMay, and also have you actually tried the version with extension after the name of the process?
Grzenio
@Grzenio: Yes, and they both work and don't work respectively in both situations. There seems to be no difference between the two.
Lance May
+1  A: 

You can do it through the registry. You were looking in the wrong place though. I knocked together a quick example for you:

private string GetJavaInstallationPath()
{
    string environmentPath = Environment.GetEnvironmentVariable("JAVA_HOME");
    if (!string.IsNullOrEmpty(environmentPath))
    {
       return environmentPath;
    }

    string javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
    using (Microsoft.Win32.RegistryKey rk = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(javaKey))
    {
        string currentVersion = rk.GetValue("CurrentVersion").ToString();
        using (Microsoft.Win32.RegistryKey key = rk.OpenSubKey(currentVersion))
        {
            return key.GetValue("JavaHome").ToString();
        }
    }
}

Then to use it, just do the following:

string installPath = GetJavaInstallationPath();
string filePath = System.IO.Path.Combine(installPath, "bin\\Java.exe");
if (System.IO.File.Exists(filePath))
{
    // We have a winner
}
GenericTypeTea
This looks perfect! Thanks for pointing out that I missed the `CurrentVersion`. I keep getting NullRef's on `rk`, though. ;(
Lance May
It is a common convention that the user can overwrite the "autodetected" java path with an environment variable called "JAVA_HOME". A programmer should respect hat and give that variable precedence: string java_path = Environment.GetEnvironmentVariable("JAVA_HOME") ?? GetJavaInstallationPath();
SchlaWiener
@Lance - I'm not a java expert, so this is only a best-guess. Have you had a look to see if the key is there?@SchlaWiener - Updated my answer to reflect your comment (I think).
GenericTypeTea
@GenericTypeTea: Yes, it is there. The keys listed in my question exist (got them through RegEdit).@SchlaWiener: Thanks a ton for that. That's something I won't have to get kicked for later. ;)
Lance May
@Lance - I don't know why it's returning null if the key's there then. It's going to be down to you to debug it I'm afraid. Please report back if you find out why.
GenericTypeTea
Even though I'm looking right at the key, I can get no further than "HKEY_LOCAL_MACHINE\SOFTWARE". At first I thought it was a path vs. key problem (since I could get into the software key just fine, but not the path copied straight from RegEdit), but even explicitly calling an `OpenSubKey()` for each step, I can't get any deeper than SOFTWARE.
Lance May
That's strange. It just comes back as null? If there was a problem I would of thought it'd be a security issue, but that would through a security exception.
GenericTypeTea
Found it! Not that it solves anything, but I found that the issue is because I'm x64 and `LocalMachine` is routing me to a subkey under SOFTWARE w/o me asking to (i.e. HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node).
Lance May
Why'd you accept? Thought you just said it didn't solve anything? No point accepting if you've not had your question answered.
GenericTypeTea
Because your code was sound, and I'm sure will work perfectly over this next hurdle (which I believe has broken scope), which I am currently writing up into another question as to not drowned this one with scope-creep. I will certainly post an edit once the other is resolved so others can benefit.
Lance May
GenericTypeTea