mono_reg_utils.py 3.3 KB

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