Browse Source

Merge pull request #2378 from glassez/python_reg

Improve Windows Registry searching for Python.
adaptive-webui-19844
sledgehammer999 10 years ago
parent
commit
aca42b8ccc
  1. 245
      src/preferences/preferences.cpp

245
src/preferences/preferences.cpp

@ -1339,145 +1339,150 @@ void Preferences::disableRecursiveDownload(bool disable) {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
namespace { namespace {
enum REG_SEARCH_TYPE {USER, SYSTEM_32BIT, SYSTEM_64BIT}; enum REG_SEARCH_TYPE
{
QStringList getRegSubkeys(const HKEY &handle) { USER,
QStringList keys; SYSTEM_32BIT,
DWORD subkeys_count = 0; SYSTEM_64BIT
DWORD max_subkey_len = 0; };
long res = ::RegQueryInfoKey(handle, NULL, NULL, NULL, &subkeys_count, &max_subkey_len, NULL, NULL, NULL, NULL, NULL, NULL);
if (res == ERROR_SUCCESS) {
max_subkey_len++; //For null character
LPTSTR key_name = new TCHAR[max_subkey_len];
for (uint i=0; i<subkeys_count; i++) {
res = ::RegEnumKeyEx(handle, 0, key_name, &max_subkey_len, NULL, NULL, NULL, NULL);
if (res == ERROR_SUCCESS)
keys.push_back(QString::fromWCharArray(key_name));
}
delete[] key_name;
}
return keys; QStringList getRegSubkeys(HKEY handle)
} {
QStringList keys;
DWORD cSubKeys = 0;
DWORD cMaxSubKeyLen = 0;
LONG res = ::RegQueryInfoKeyW(handle, NULL, NULL, NULL, &cSubKeys, &cMaxSubKeyLen, NULL, NULL, NULL, NULL, NULL, NULL);
if (res == ERROR_SUCCESS) {
cMaxSubKeyLen++; // For null character
LPWSTR lpName = new WCHAR[cMaxSubKeyLen];
DWORD cName;
for (DWORD i = 0; i < cSubKeys; ++i) {
cName = cMaxSubKeyLen;
res = ::RegEnumKeyExW(handle, 0, lpName, &cName, NULL, NULL, NULL, NULL);
if (res == ERROR_SUCCESS)
keys.push_back(QString::fromWCharArray(lpName));
}
QString getRegValue(const HKEY &handle, const QString &name = QString()) { delete[] lpName;
QString end_result; }
DWORD type = 0;
DWORD size = 0;
DWORD array_size = 0;
LPTSTR value_name = NULL; return keys;
if (!name.isEmpty()) { }
value_name = new TCHAR[name.size()+1];
name.toWCharArray(value_name);
value_name[name.size()] = '\0';
}
// Discover the size of the value QString getRegValue(HKEY handle, const QString &name = QString())
::RegQueryValueEx(handle, value_name, NULL, &type, NULL, &size); {
array_size = size / sizeof(TCHAR); QString result;
if (size % sizeof(TCHAR))
array_size++; DWORD type = 0;
array_size++; //For null character DWORD cbData = 0;
LPTSTR value = new TCHAR[array_size]; LPWSTR lpValueName = NULL;
if (!name.isEmpty()) {
long res = ::RegQueryValueEx(handle, value_name, NULL, &type, (LPBYTE)value, &size); lpValueName = new WCHAR[name.size() + 1];
if (res == ERROR_SUCCESS) { name.toWCharArray(lpValueName);
value[array_size] = '\0'; lpValueName[name.size()] = 0;
end_result = QString::fromWCharArray(value); }
}
if (value_name) // Discover the size of the value
delete[] value_name; ::RegQueryValueExW(handle, lpValueName, NULL, &type, NULL, &cbData);
if (value) DWORD cBuffer = (cbData / sizeof(WCHAR)) + 1;
delete[] value; LPWSTR lpData = new WCHAR[cBuffer];
LONG res = ::RegQueryValueExW(handle, lpValueName, NULL, &type, (LPBYTE)lpData, &cbData);
if (lpValueName)
delete[] lpValueName;
if (res == ERROR_SUCCESS) {
lpData[cBuffer - 1] = 0;
result = QString::fromWCharArray(lpData);
}
delete[] lpData;
return end_result; return result;
} }
QString pythonSearchReg(const REG_SEARCH_TYPE type) { QString pythonSearchReg(const REG_SEARCH_TYPE type)
HKEY key_handle1; {
long res = 0; HKEY hkRoot;
if (type == USER)
hkRoot = HKEY_CURRENT_USER;
else
hkRoot = HKEY_LOCAL_MACHINE;
REGSAM samDesired = KEY_READ;
if (type == SYSTEM_32BIT)
samDesired |= KEY_WOW64_32KEY;
else if (type == SYSTEM_64BIT)
samDesired |= KEY_WOW64_64KEY;
QString path;
LONG res = 0;
HKEY hkPythonCore;
res = ::RegOpenKeyExW(hkRoot, L"SOFTWARE\\Python\\PythonCore", 0, samDesired, &hkPythonCore);
if (res == ERROR_SUCCESS) {
QStringList versions = getRegSubkeys(hkPythonCore);
qDebug("Python versions nb: %d", versions.size());
versions.sort();
bool found = false;
while(!found && !versions.empty()) {
const QString version = versions.takeLast() + "\\InstallPath";
LPWSTR lpSubkey = new WCHAR[version.size() + 1];
version.toWCharArray(lpSubkey);
lpSubkey[version.size()] = 0;
HKEY hkInstallPath;
res = ::RegOpenKeyExW(hkPythonCore, lpSubkey, 0, samDesired, &hkInstallPath);
delete[] lpSubkey;
if (res == ERROR_SUCCESS) {
qDebug("Detected possible Python v%s location", qPrintable(version));
path = getRegValue(hkInstallPath);
::RegCloseKey(hkInstallPath);
if (!path.isEmpty() && QDir(path).exists("python.exe")) {
qDebug("Found python.exe at %s", qPrintable(path));
found = true;
}
}
}
switch (type) { if (!found)
case USER: path = QString();
res = ::RegOpenKeyEx(HKEY_CURRENT_USER, TEXT("SOFTWARE\\Python\\PythonCore"), 0, KEY_READ, &key_handle1);
break;
case SYSTEM_32BIT:
res = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Python\\PythonCore"), 0, KEY_READ|KEY_WOW64_32KEY, &key_handle1);
break;
case SYSTEM_64BIT:
res = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Python\\PythonCore"), 0, KEY_READ|KEY_WOW64_64KEY, &key_handle1);
break;
}
if (res == ERROR_SUCCESS) { ::RegCloseKey(hkPythonCore);
QStringList versions = getRegSubkeys(key_handle1);
qDebug("Python versions nb: %d", versions.size());
versions.sort();
while(!versions.empty()) {
const QString version = versions.takeLast()+"\\InstallPath";
HKEY key_handle2;
LPTSTR subkey = new TCHAR[version.size()+1];
version.toWCharArray(subkey);
subkey[version.size()] = '\0';
switch (type) {
case USER:
res = ::RegOpenKeyEx(key_handle1, subkey, 0, KEY_READ, &key_handle2);
break;
case SYSTEM_32BIT:
res = ::RegOpenKeyEx(key_handle1, subkey, 0, KEY_READ|KEY_WOW64_32KEY, &key_handle2);
break;
case SYSTEM_64BIT:
res = ::RegOpenKeyEx(key_handle1, subkey, 0, KEY_READ|KEY_WOW64_64KEY, &key_handle2);
break;
}
delete[] subkey;
if (res == ERROR_SUCCESS) {
qDebug("Detected possible Python v%s location", qPrintable(version));
QString path = getRegValue(key_handle2);
::RegCloseKey(key_handle2);
if (!path.isEmpty() && QDir(path).exists("python.exe")) {
qDebug("Found python.exe at %s", qPrintable(path));
::RegCloseKey(key_handle1);
return path;
}
}
else
::RegCloseKey(key_handle2);
} }
}
::RegCloseKey(key_handle1); return path;
return QString::null;
} }
} }
QString Preferences::getPythonPath() { QString Preferences::getPythonPath()
QString path = pythonSearchReg(USER); {
if (path.isEmpty()) QString path = pythonSearchReg(USER);
if (!path.isEmpty())
return path;
path = pythonSearchReg(SYSTEM_32BIT); path = pythonSearchReg(SYSTEM_32BIT);
else return path; if (!path.isEmpty())
return path;
if (path.isEmpty())
path = pythonSearchReg(SYSTEM_64BIT); path = pythonSearchReg(SYSTEM_64BIT);
else return path; if (!path.isEmpty())
return path;
if (!path.isEmpty())
return path; // Fallback: Detect python from default locations
QStringList supported_versions;
supported_versions << "32" << "31" << "30" << "27" << "26" << "25";
foreach (const QString &v, supported_versions) {
if (QFile::exists("C:/Python" + v + "/python.exe"))
return "C:/Python" + v;
}
// Fallback: Detect python from default locations return QString();
QStringList supported_versions;
supported_versions << "32" << "31" << "30" << "27" << "26" << "25";
foreach (const QString &v, supported_versions) {
if (QFile::exists("C:/Python"+v+"/python.exe"))
return "C:/Python"+v;
}
return QString::null;
} }
bool Preferences::neverCheckFileAssoc() const { bool Preferences::neverCheckFileAssoc() const {

Loading…
Cancel
Save