mono_reg_utils.py 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import os
  2. import platform
  3. if os.name == "nt":
  4. import sys
  5. import winreg
  6. def _reg_open_key(key, subkey):
  7. try:
  8. return winreg.OpenKey(key, subkey)
  9. except OSError:
  10. if platform.architecture()[0] == "32bit":
  11. bitness_sam = winreg.KEY_WOW64_64KEY
  12. else:
  13. bitness_sam = winreg.KEY_WOW64_32KEY
  14. return winreg.OpenKey(key, subkey, 0, winreg.KEY_READ | bitness_sam)
  15. def _reg_open_key_bits(key, subkey, bits):
  16. sam = winreg.KEY_READ
  17. if platform.architecture()[0] == "32bit":
  18. if bits == "64":
  19. # Force 32bit process to search in 64bit registry
  20. sam |= winreg.KEY_WOW64_64KEY
  21. else:
  22. if bits == "32":
  23. # Force 64bit process to search in 32bit registry
  24. sam |= winreg.KEY_WOW64_32KEY
  25. return winreg.OpenKey(key, subkey, 0, sam)
  26. def _find_mono_in_reg(subkey, bits):
  27. try:
  28. with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
  29. value = winreg.QueryValueEx(hKey, "SdkInstallRoot")[0]
  30. return value
  31. except OSError:
  32. return None
  33. def _find_mono_in_reg_old(subkey, bits):
  34. try:
  35. with _reg_open_key_bits(winreg.HKEY_LOCAL_MACHINE, subkey, bits) as hKey:
  36. default_clr = winreg.QueryValueEx(hKey, "DefaultCLR")[0]
  37. if default_clr:
  38. return _find_mono_in_reg(subkey + "\\" + default_clr, bits)
  39. return None
  40. except OSError:
  41. return None
  42. def find_mono_root_dir(bits):
  43. root_dir = _find_mono_in_reg(r"SOFTWARE\Mono", bits)
  44. if root_dir is not None:
  45. return str(root_dir)
  46. root_dir = _find_mono_in_reg_old(r"SOFTWARE\Novell\Mono", bits)
  47. if root_dir is not None:
  48. return str(root_dir)
  49. return ""
  50. def find_msbuild_tools_path_reg():
  51. import subprocess
  52. vswhere = os.getenv("PROGRAMFILES(X86)")
  53. if not vswhere:
  54. vswhere = os.getenv("PROGRAMFILES")
  55. vswhere += r"\Microsoft Visual Studio\Installer\vswhere.exe"
  56. vswhere_args = ["-latest", "-products", "*", "-requires", "Microsoft.Component.MSBuild"]
  57. try:
  58. lines = subprocess.check_output([vswhere] + vswhere_args).splitlines()
  59. for line in lines:
  60. parts = line.decode("utf-8").split(":", 1)
  61. if len(parts) < 2 or parts[0] != "installationPath":
  62. continue
  63. val = parts[1].strip()
  64. if not val:
  65. raise ValueError("Value of `installationPath` entry is empty")
  66. # Since VS2019, the directory is simply named "Current"
  67. msbuild_dir = os.path.join(val, "MSBuild\\Current\\Bin")
  68. if os.path.isdir(msbuild_dir):
  69. return msbuild_dir
  70. # Directory name "15.0" is used in VS 2017
  71. return os.path.join(val, "MSBuild\\15.0\\Bin")
  72. raise ValueError("Cannot find `installationPath` entry")
  73. except ValueError as e:
  74. print("Error reading output from vswhere: " + e.message)
  75. except OSError:
  76. pass # Fine, vswhere not found
  77. except (subprocess.CalledProcessError, OSError):
  78. pass
  79. # Try to find 14.0 in the Registry
  80. try:
  81. subkey = r"SOFTWARE\Microsoft\MSBuild\ToolsVersions\14.0"
  82. with _reg_open_key(winreg.HKEY_LOCAL_MACHINE, subkey) as hKey:
  83. value = winreg.QueryValueEx(hKey, "MSBuildToolsPath")[0]
  84. return value
  85. except OSError:
  86. return ""