mono_reg_utils.py 3.6 KB

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