Search code examples
c++windowsjava-home

c++ programmatically retrieve java.exe path


I'm trying to retrieve the java.exe installation path on Windows. However, I can't succeed so far.

What I have tried are:

  1. getenv("JAVA_HOME"), which is rarely set in my opinion (mostly returns nothing, since it isn't set?)
  2. CMD the command for %i in (java.exe) do @echo. %~$PATH:i, which returns me the path when executed manually in cmd, however I can't retrieve it programmatically in c++? _popen returns me nothing when I execute this code, however a simple dir statement does return me the right output (directory listing).

So, all I want is to retrieve the path where java.exe is located, which I need in my application. Please if you have any good ideas, let me know. I'm willing to fix this issue.

string cmd(char *command) {
    FILE *fpipe;
    string response = "";
    char c = 0;
    if (0 == (fpipe = (FILE*)_popen(command, "r"))) {
        Exit("popen() failed.");
    }
    while (fread(&c, sizeof c, 1, fpipe)) {
        //printf("%c", c);
        response += c;
    }
    _pclose(fpipe);
    return response;
}
cout << cmd("for %i in (java.exe) do @echo. %~$PATH:i") << endl; //EMPTY (MANUAL ON CMD RETURNS THE RIGHT PATH)
cout << cmd("dir"); //RETURNS LIST OF CONTENTS

Solution

  • If you want your application to run on a wide variety of machines, you cannot assume any fixed paths and you usually cannot assume that certain environment variables are set. The user can almost always choose a completely arbitrary install location. More often than not the only decently reliable way to get information about the install location of a program is through the Windows registry. And even that assumes installation through an installer that actually writes that information to the registry.

    Finding the JRE install path in the Win Registry

    For the Oracle Java Runtime all the info you need is stored in the registry provided it was installed with its own installer.

    The relevat registry paths depend on the type of Java and the type of Windows.

    64bit Java on 64bit Windows or 32bit Java on 32bit Windows:

    HKEY_LOCAL_MACHINE\SOFTWARE\JavaSoft\Java Runtime Environment
    

    32bit Java on 64bit Windows:

    HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment
    

    That key has an entry CurrentVersion that contains the newest installed version number. It also has a number of sub-keys, at least one for each installed version of the Java Runtime. Those keys have an entry JavaHome that contains the top-level Java installation directory. I’m not too familiar with Java, but I assume that starting at that location the directory and file layout is fixed so that you can assume that java.exe can always be found in the same path relative to JavaHome.

    To make this a bit clearer assume you have version 1.8.0_111 installed as the newest version.

    • Your CurrentVersion entry will be “1.8”.
    • You’ll have two sub-keys for that version.

      ...\Java Runtime Environment\1.8
      ...\Java Runtime Environment\1.8.0_111
      
    • Both sub-keys will have a JavaHome entry pointing to the install directory, for example: “C:\Program Files (x86)\Java\jre1.8.0_111”.

    Accessing the Registry with C++

    You could use the WinAPI directly. For your simple task of querying a few keys that could even be reasonable. There is also a whole bunch of libraries out there that wrap the WinAPI and give you a more C++ like interface to the WinAPI registry functions. I haven’t used any of them, so I can’t recommend one.