First draft of multiple Java installation detection on Windows
This commit is contained in:
		| @@ -185,9 +185,9 @@ void SettingsDialog::loadSettings(SettingsObject *s) | ||||
| void SettingsDialog::on_pushButton_clicked() | ||||
| { | ||||
| 	JavaUtils jut; | ||||
| 	QStringList paths = jut.FindJavaPath(); | ||||
| 	auto javas = jut.FindJavaPaths(); | ||||
|  | ||||
| 	ui->javaPathTextBox->setText(paths.at(0)); | ||||
| 	ui->javaPathTextBox->setText(std::get<JI_PATH>(javas.at(0))); | ||||
| } | ||||
|  | ||||
| void SettingsDialog::on_btnBrowse_clicked() | ||||
|   | ||||
| @@ -374,6 +374,12 @@ | ||||
|          <layout class="QGridLayout" name="gridLayout_3"> | ||||
|           <item row="0" column="0"> | ||||
|            <widget class="QLabel" name="labelJavaPath"> | ||||
|             <property name="sizePolicy"> | ||||
|              <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||||
|               <horstretch>0</horstretch> | ||||
|               <verstretch>0</verstretch> | ||||
|              </sizepolicy> | ||||
|             </property> | ||||
|             <property name="text"> | ||||
|              <string>Java path:</string> | ||||
|             </property> | ||||
| @@ -381,6 +387,12 @@ | ||||
|           </item> | ||||
|           <item row="2" column="0"> | ||||
|            <widget class="QLabel" name="labelJVMArgs"> | ||||
|             <property name="sizePolicy"> | ||||
|              <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||||
|               <horstretch>0</horstretch> | ||||
|               <verstretch>0</verstretch> | ||||
|              </sizepolicy> | ||||
|             </property> | ||||
|             <property name="text"> | ||||
|              <string>JVM arguments:</string> | ||||
|             </property> | ||||
| @@ -402,9 +414,6 @@ | ||||
|           <item row="0" column="1" colspan="3"> | ||||
|            <widget class="QLineEdit" name="javaPathTextBox"/> | ||||
|           </item> | ||||
|           <item row="2" column="1" colspan="3"> | ||||
|            <widget class="QLineEdit" name="jvmArgsTextBox"/> | ||||
|           </item> | ||||
|           <item row="1" column="2"> | ||||
|            <widget class="QPushButton" name="pushButton"> | ||||
|             <property name="sizePolicy"> | ||||
| @@ -418,6 +427,9 @@ | ||||
|             </property> | ||||
|            </widget> | ||||
|           </item> | ||||
|           <item row="2" column="1" colspan="3"> | ||||
|            <widget class="QLineEdit" name="jvmArgsTextBox"/> | ||||
|           </item> | ||||
|          </layout> | ||||
|         </widget> | ||||
|        </item> | ||||
|   | ||||
| @@ -14,7 +14,6 @@ | ||||
|  */ | ||||
|  | ||||
| #include "JavaUtils.h" | ||||
| #include "osutils.h" | ||||
| #include "pathutils.h" | ||||
|  | ||||
| #include <QStringList> | ||||
| @@ -22,27 +21,33 @@ | ||||
| #include <QDir> | ||||
| #include <logger/QsLog.h> | ||||
|  | ||||
| #if WINDOWS | ||||
| #include <windows.h> | ||||
|  | ||||
| #endif | ||||
|  | ||||
| JavaUtils::JavaUtils() | ||||
| { | ||||
|  | ||||
| } | ||||
|  | ||||
| #if WINDOWS | ||||
| QStringList JavaUtils::FindJavaPath() | ||||
| std::vector<java_install> JavaUtils::GetDefaultJava() | ||||
| { | ||||
| 	QStringList paths; | ||||
| 	std::vector<java_install> javas; | ||||
| 	javas.push_back(std::make_tuple("java", "unknown", "java", false)); | ||||
|  | ||||
| 	return javas; | ||||
| } | ||||
|  | ||||
| #if WINDOWS | ||||
| std::vector<java_install> JavaUtils::FindJavaFromRegistryKey(DWORD keyType, QString keyName) | ||||
| { | ||||
| 	std::vector<java_install> javas; | ||||
|  | ||||
| 	QString archType = "unknown"; | ||||
| 	if(keyType == KEY_WOW64_64KEY) archType = "64"; | ||||
| 	else if(keyType == KEY_WOW64_32KEY) archType = "32"; | ||||
|  | ||||
| 	HKEY jreKey; | ||||
| 	QString jreKeyName = "SOFTWARE\\JavaSoft\\Java Runtime Environment"; | ||||
| 	if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, jreKeyName.toStdString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &jreKey) == ERROR_SUCCESS) | ||||
| 	if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyName.toStdString().c_str(), 0, KEY_READ | keyType | KEY_ENUMERATE_SUB_KEYS, &jreKey) == ERROR_SUCCESS) | ||||
| 	{ | ||||
| 		// Read the current JRE version from the registry. | ||||
| 		// This will be used to find the key that contains the JavaHome value. | ||||
| 		// Read the current type version from the registry. | ||||
| 		// This will be used to find any key that contains the JavaHome value. | ||||
| 		char *value = new char[0]; | ||||
| 		DWORD valueSz = 0; | ||||
| 		if (RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE*)value, &valueSz) == ERROR_MORE_DATA) | ||||
| @@ -51,64 +56,102 @@ QStringList JavaUtils::FindJavaPath() | ||||
| 			RegQueryValueExA(jreKey, "CurrentVersion", NULL, NULL, (BYTE*)value, &valueSz); | ||||
| 		} | ||||
|  | ||||
| 		RegCloseKey(jreKey); | ||||
| 		QString recommended = value; | ||||
|  | ||||
| 		// Now open the registry key for the JRE version that we just got. | ||||
| 		jreKeyName.append("\\").append(value); | ||||
| 		if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, jreKeyName.toStdString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &jreKey) == ERROR_SUCCESS) | ||||
| 		TCHAR subKeyName[255]; | ||||
| 		DWORD subKeyNameSize, numSubKeys, retCode; | ||||
|  | ||||
| 		// Get the number of subkeys | ||||
| 		RegQueryInfoKey(jreKey, NULL, NULL, NULL, &numSubKeys, NULL, NULL, NULL, NULL, NULL, NULL, NULL); | ||||
|  | ||||
| 		// Iterate until RegEnumKeyEx fails | ||||
| 		if(numSubKeys > 0) | ||||
| 		{ | ||||
| 			// Read the JavaHome value to find where Java is installed. | ||||
| 			value = new char[0]; | ||||
| 			valueSz = 0; | ||||
| 			if (RegQueryValueExA(jreKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz) == ERROR_MORE_DATA) | ||||
| 			for(int i = 0; i < numSubKeys; i++) | ||||
| 			{ | ||||
| 				value = new char[valueSz]; | ||||
| 				RegQueryValueExA(jreKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz); | ||||
| 				subKeyNameSize = 255; | ||||
| 				retCode = RegEnumKeyEx(jreKey, i, subKeyName, &subKeyNameSize, NULL, NULL, NULL, NULL); | ||||
| 				if(retCode == ERROR_SUCCESS) | ||||
| 				{ | ||||
| 					// Now open the registry key for the version that we just got. | ||||
| 					QString newKeyName = keyName + "\\" + subKeyName; | ||||
|  | ||||
| 				paths << QDir(PathCombine(value, "bin")).absoluteFilePath("java.exe"); | ||||
| 					HKEY newKey; | ||||
| 					if(RegOpenKeyEx(HKEY_LOCAL_MACHINE, newKeyName.toStdString().c_str(), 0, KEY_READ | KEY_WOW64_64KEY, &newKey) == ERROR_SUCCESS) | ||||
| 					{ | ||||
| 						// Read the JavaHome value to find where Java is installed. | ||||
| 						value = new char[0]; | ||||
| 						valueSz = 0; | ||||
| 						if (RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz) == ERROR_MORE_DATA) | ||||
| 						{ | ||||
| 							value = new char[valueSz]; | ||||
| 							RegQueryValueEx(newKey, "JavaHome", NULL, NULL, (BYTE*)value, &valueSz); | ||||
|  | ||||
| 							javas.push_back(std::make_tuple(subKeyName, archType, QDir(PathCombine(value, "bin")).absoluteFilePath("java.exe"), (recommended == subKeyName))); | ||||
| 						} | ||||
|  | ||||
| 						RegCloseKey(newKey); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			RegCloseKey(jreKey); | ||||
| 		} | ||||
|  | ||||
| 		RegCloseKey(jreKey); | ||||
| 	} | ||||
|  | ||||
| 	if(paths.length() <= 0) | ||||
| 	return javas; | ||||
| } | ||||
|  | ||||
| std::vector<java_install> JavaUtils::FindJavaPaths() | ||||
| {			 | ||||
| 	std::vector<java_install> JRE64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); | ||||
| 	std::vector<java_install> JDK64s = this->FindJavaFromRegistryKey(KEY_WOW64_64KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); | ||||
| 	std::vector<java_install> JRE32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Runtime Environment"); | ||||
| 	std::vector<java_install> JDK32s = this->FindJavaFromRegistryKey(KEY_WOW64_32KEY, "SOFTWARE\\JavaSoft\\Java Development Kit"); | ||||
|  | ||||
| 	std::vector<java_install> javas; | ||||
| 	javas.insert(javas.end(), JRE64s.begin(), JRE64s.end()); | ||||
| 	javas.insert(javas.end(), JDK64s.begin(), JDK64s.end()); | ||||
| 	javas.insert(javas.end(), JRE32s.begin(), JRE32s.end()); | ||||
| 	javas.insert(javas.end(), JDK32s.begin(), JDK32s.end()); | ||||
|  | ||||
| 	if(javas.size() <= 0) | ||||
| 	{ | ||||
| 		QLOG_WARN() << "Failed to find Java in the Windows registry - defaulting to \"java\""; | ||||
| 		paths << "java"; | ||||
| 		return this->GetDefaultJava(); | ||||
| 	} | ||||
|  | ||||
| 	return paths; | ||||
| 	QLOG_INFO() << "Found the following Java installations (64 -> 32, JRE -> JDK): "; | ||||
|  | ||||
| 	for(auto &java : javas) | ||||
| 	{ | ||||
| 		QString sRec; | ||||
| 		if(std::get<JI_REC>(java)) sRec = "(Recommended)"; | ||||
| 		QLOG_INFO() << std::get<JI_ID>(java) << std::get<JI_ARCH>(java) << " at " << std::get<JI_PATH>(java) << sRec; | ||||
| 	} | ||||
|  | ||||
| 	return javas; | ||||
| } | ||||
| #elif OSX | ||||
| QStringList JavaUtils::FindJavaPath() | ||||
| std::vector<java_install> JavaUtils::FindJavaPath() | ||||
| { | ||||
| 	QLOG_INFO() << "OS X Java detection incomplete - defaulting to \"java\""; | ||||
|  | ||||
| 	QStringList paths; | ||||
| 	paths << "java"; | ||||
|  | ||||
| 	return paths; | ||||
| 	return this->GetDefaultPath(); | ||||
| } | ||||
|  | ||||
| #elif LINUX | ||||
| QStringList JavaUtils::FindJavaPath() | ||||
| std::vector<java_install> JavaUtils::FindJavaPath() | ||||
| { | ||||
| 	QLOG_INFO() << "Linux Java detection incomplete - defaulting to \"java\""; | ||||
|  | ||||
| 	QStringList paths; | ||||
| 	paths << "java"; | ||||
|  | ||||
| 	return paths; | ||||
| 	return this->GetDefaultPath(); | ||||
| } | ||||
| #else | ||||
| QStringList JavaUtils::FindJavaPath() | ||||
| std::vector<java_install> JavaUtils::FindJavaPath() | ||||
| { | ||||
| 	QLOG_INFO() << "Unknown operating system build - defaulting to \"java\""; | ||||
|  | ||||
| 	QStringList paths; | ||||
| 	paths << "java"; | ||||
|  | ||||
| 	return paths; | ||||
| 	return this->GetDefaultPath(); | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -17,10 +17,28 @@ | ||||
|  | ||||
| #include <QStringList> | ||||
|  | ||||
| #include "osutils.h" | ||||
|  | ||||
| #if WINDOWS | ||||
| 	#include <windows.h> | ||||
| #endif | ||||
|  | ||||
| #define JI_ID 0 | ||||
| #define JI_ARCH 1 | ||||
| #define JI_PATH 2 | ||||
| #define JI_REC 3 | ||||
| typedef std::tuple<QString, QString, QString, bool> java_install; | ||||
|  | ||||
| class JavaUtils | ||||
| { | ||||
| public: | ||||
| 	JavaUtils(); | ||||
|  | ||||
| 	QStringList FindJavaPath(); | ||||
| 	std::vector<java_install> FindJavaPaths(); | ||||
|  | ||||
| private: | ||||
| 	std::vector<java_install> GetDefaultJava(); | ||||
| #if WINDOWS | ||||
| 	std::vector<java_install> FindJavaFromRegistryKey(DWORD keyType, QString keyName); | ||||
| #endif | ||||
| }; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user