How to determine Windows Java installation location

21,332

Solution 1

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
}

Solution 2

Just a quick bump because i found a better solution than the owner picked answer.

I found that it works with only 32bit Java and today time, thats pretty outdated. Therefor I made a adjustment for 64bit systems. Hope this helps anyone else looking for a way to pull the paths.

        private string GetJavaInstallationPath()
        {
            string environmentPath = Environment.GetEnvironmentVariable("JAVA_HOME");
            if (!string.IsNullOrEmpty(environmentPath))
            {
                return environmentPath;
            }
            string javaKey = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";
            if (!Environment.Is64BitOperatingSystem)
            {
                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();
                    }
                }
            }
            else
            {
                using (var view64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine,
                                                            RegistryView.Registry64))
                {
                    using (var clsid64 = view64.OpenSubKey(javaKey))
                    {
                        string currentVersion = clsid64.GetValue("CurrentVersion").ToString();
                        using (RegistryKey key = clsid64.OpenSubKey(currentVersion))
                        {
                            return key.GetValue("JavaHome").ToString();
                        }
                    }
                }
            }

        }

Solution 3

Building on top of @GenericTypeTea question - this is a way how to check both on x32/x64.

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

  const string JAVA_KEY = "SOFTWARE\\JavaSoft\\Java Runtime Environment\\";

  var localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry32);
  using (var rk = localKey.OpenSubKey(JAVA_KEY))
  {
    if (rk != null)
    {
      string currentVersion = rk.GetValue("CurrentVersion").ToString();
      using (var key = rk.OpenSubKey(currentVersion))
      {
        return key.GetValue("JavaHome").ToString();
      }
    }
  }

  localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64);
  using (var rk = localKey.OpenSubKey(JAVA_KEY))
  {
    if (rk != null)
    {
      string currentVersion = rk.GetValue("CurrentVersion").ToString();
      using (var key = rk.OpenSubKey(currentVersion))
      {
        return key.GetValue("JavaHome").ToString();
      }
    }
  }

  return null;
}

Solution 4

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.

Share:
21,332
Lance
Author by

Lance

I live a dual life as a automation/software/web/mobile/graphic designer/developer for Corporate America... and indie game vigilante. By day I monkey the codes for The Rawlings Group, but by night I wear all of the many hats of Nekoyoubi Games (just kidding; haven't had an evening in years). Follow me on Twitter (@Nekoyoubi) if you're into that sort of thing, and watch as I say absolutely nothing. ;Þ

Updated on September 10, 2020

Comments

  • Lance
    Lance over 3 years

    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();
        }
    }
    
  • Lance
    Lance almost 14 years
    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.
  • Grzenio
    Grzenio almost 14 years
    Could you check which java.exe process runs when you run it from command prompt?
  • Grzenio
    Grzenio almost 14 years
    @LanceMay, and also have you actually tried the version with extension after the name of the process?
  • Lance
    Lance almost 14 years
    Yes, and they both work and don't work respectively in both situations. There seems to be no difference between the two.
  • Lance
    Lance almost 14 years
    This looks perfect! Thanks for pointing out that I missed the CurrentVersion. I keep getting NullRef's on rk, though. ;(
  • Jürgen Steinblock
    Jürgen Steinblock almost 14 years
    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();
  • djdd87
    djdd87 almost 14 years
    @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).
  • Lance
    Lance almost 14 years
    @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. ;)
  • djdd87
    djdd87 almost 14 years
    @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.
  • Lance
    Lance almost 14 years
    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.
  • djdd87
    djdd87 almost 14 years
    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.
  • Lance
    Lance almost 14 years
    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).
  • djdd87
    djdd87 almost 14 years
    Why'd you accept? Thought you just said it didn't solve anything? No point accepting if you've not had your question answered.
  • Lance
    Lance almost 14 years
    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.
  • SimplyInk
    SimplyInk about 8 years
    msdn.microsoft.com/en-us/library/dd411615(v=vs.110).aspx On the 64-bit versions of Windows, portions of the registry are stored separately for 32-bit and 64-bit applications. There is a 32-bit view for 32-bit applications and a 64-bit view for 64-bit applications. If view is Registry64 but the remote machine is running a 32-bit operating system, the returned key will use the Registry32 view.
  • SimplyInk
    SimplyInk about 8 years
    Therefore just the call to open the key from the Registry64 view is enough to cover both 32/64-bit OS cases.