|
| 1 | +import re |
| 2 | +import sys |
| 3 | +import os |
| 4 | +from ctypes import * |
| 5 | + |
| 6 | +root_dir = os.path.dirname(__file__) |
| 7 | +sys.path.insert(0, os.path.join(root_dir, 'comtypes')) |
| 8 | + |
| 9 | +from comtypes import IUnknown |
| 10 | +from comtypes import GUID |
| 11 | +from comtypes import COMMETHOD |
| 12 | +from comtypes import BSTR |
| 13 | +from comtypes import DWORD |
| 14 | +from comtypes.safearray import _midlSAFEARRAY |
| 15 | +from comtypes.client import CreateObject |
| 16 | + |
| 17 | +""" Find Visual Studio 2017 C/C++ compiler install location """ |
| 18 | + |
| 19 | + |
| 20 | +class ISetupInstance(IUnknown): |
| 21 | + _iid_ = GUID('{B41463C3-8866-43B5-BC33-2B0676F7F42E}') |
| 22 | + _methods_ = [ |
| 23 | + COMMETHOD([], HRESULT, 'GetInstanceId', |
| 24 | + ( ['out'], POINTER(BSTR), 'pbstrInstanceId' ) ), |
| 25 | + COMMETHOD([], HRESULT, 'GetInstallDate', |
| 26 | + ( ['out'], POINTER(c_ulonglong), 'pInstallDate') ), |
| 27 | + COMMETHOD([], HRESULT, 'GetInstallationName', |
| 28 | + ( ['out'], POINTER(BSTR), 'pInstallationName') ), |
| 29 | + COMMETHOD([], HRESULT, 'GetInstallationPath', |
| 30 | + ( ['out'], POINTER(BSTR), 'pInstallationPath') ), |
| 31 | + COMMETHOD([], HRESULT, 'GetInstallationVersion', |
| 32 | + ( ['out'], POINTER(BSTR), 'pInstallationVersion') ), |
| 33 | + COMMETHOD([], HRESULT, 'GetDisplayName', |
| 34 | + ( ['in'], DWORD, 'lcid' ), |
| 35 | + ( ['out'], POINTER(BSTR), 'pDisplayName') ), |
| 36 | + COMMETHOD([], HRESULT, 'GetDescription', |
| 37 | + ( ['in'], DWORD, 'lcid' ), |
| 38 | + ( ['out'], POINTER(BSTR), 'pDescription') ), |
| 39 | + COMMETHOD([], HRESULT, 'ResolvePath', |
| 40 | + ( ['in'], c_wchar_p, 'pRelativePath' ), |
| 41 | + ( ['out'], POINTER(BSTR), 'pAbsolutePath') ), |
| 42 | + ] |
| 43 | + |
| 44 | +class ISetupPackageReference(IUnknown): |
| 45 | + _iid_ = GUID('{da8d8a16-b2b6-4487-a2f1-594ccccd6bf5}') |
| 46 | + _methods_ = [ |
| 47 | + COMMETHOD([], HRESULT, 'GetId', |
| 48 | + ( ['out'], POINTER(BSTR), 'pOut' ) ), |
| 49 | + COMMETHOD([], HRESULT, 'GetVersion', |
| 50 | + ( ['out'], POINTER(BSTR), 'pOut' ) ), |
| 51 | + COMMETHOD([], HRESULT, 'GetChip', |
| 52 | + ( ['out'], POINTER(BSTR), 'pOut' ) ), |
| 53 | + COMMETHOD([], HRESULT, 'GetLanguage', |
| 54 | + ( ['out'], POINTER(BSTR), 'pOut' ) ), |
| 55 | + COMMETHOD([], HRESULT, 'GetBranch', |
| 56 | + ( ['out'], POINTER(BSTR), 'pOut' ) ), |
| 57 | + COMMETHOD([], HRESULT, 'GetType', |
| 58 | + ( ['out'], POINTER(BSTR), 'pOut' ) ), |
| 59 | + COMMETHOD([], HRESULT, 'GetUniqueId', |
| 60 | + ( ['out'], POINTER(BSTR), 'pOut' ) ) |
| 61 | + ] |
| 62 | + |
| 63 | +class ISetupInstance2(ISetupInstance): |
| 64 | + _iid_ = GUID('{89143C9A-05AF-49B0-B717-72E218A2185C}') |
| 65 | + _methods_ = [ |
| 66 | + COMMETHOD([], HRESULT, 'GetState', |
| 67 | + ( ['out'], POINTER(DWORD), 'pState' ) ), |
| 68 | + COMMETHOD([], HRESULT, 'GetPackages', |
| 69 | + ( ['out'], POINTER(_midlSAFEARRAY(POINTER(ISetupPackageReference))), 'ppPackage' ) ) |
| 70 | + ] |
| 71 | + |
| 72 | +class IEnumSetupInstances(IUnknown): |
| 73 | + _iid_ = GUID('{6380BCFF-41D3-4B2E-8B2E-BF8A6810C848}') |
| 74 | + _methods_ = [ |
| 75 | + COMMETHOD([], HRESULT, 'Next', |
| 76 | + ( ['in'], c_ulong, 'celt'), |
| 77 | + ( ['out'], POINTER(POINTER(ISetupInstance)), 'rgelt' ), |
| 78 | + ( ['out'], POINTER(c_ulong), 'pceltFetched' ) ), |
| 79 | + COMMETHOD([], HRESULT, 'Skip', |
| 80 | + ( ['in'], c_ulong, 'celt' ) ), |
| 81 | + COMMETHOD([], HRESULT, 'Reset'), |
| 82 | + ] |
| 83 | + |
| 84 | +class ISetupConfiguration(IUnknown): |
| 85 | + _iid_ = GUID('{42843719-DB4C-46C2-8E7C-64F1816EFD5B}') |
| 86 | + _methods_ = [ |
| 87 | + COMMETHOD([], HRESULT, 'EnumInstances', |
| 88 | + ( ['out'], POINTER(POINTER(IEnumSetupInstances)), 'ppIESI' ) ), |
| 89 | + COMMETHOD([], HRESULT, 'GetInstanceForCurrentProcess', |
| 90 | + ( ['out'], POINTER(POINTER(ISetupInstance)), 'ppISI' ) ), |
| 91 | + COMMETHOD([], HRESULT, 'GetInstanceForPath', |
| 92 | + ( ['in'], c_wchar_p, 'wzPath'), |
| 93 | + ( ['out'], POINTER(POINTER(ISetupInstance)), 'ppISI' ) ) |
| 94 | + ] |
| 95 | + |
| 96 | +class ISetupConfiguration2(ISetupConfiguration) : |
| 97 | + _iid_ = GUID('{26AAB78C-4A60-49D6-AF3B-3C35BC93365D}') |
| 98 | + _methods_ = [ |
| 99 | + COMMETHOD([], HRESULT, 'EnumAllInstances', |
| 100 | + ( ['out'], POINTER(POINTER(IEnumSetupInstances)), 'ppIEnumSetupInstances' ) ) |
| 101 | + ] |
| 102 | + |
| 103 | + |
| 104 | +def GetVS2017CPPBasePath(): |
| 105 | + installs = [] |
| 106 | + iface = CreateObject(GUID('{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}')) |
| 107 | + setupConfiguration = iface.QueryInterface(ISetupConfiguration2) |
| 108 | + allInstances = setupConfiguration.EnumAllInstances() |
| 109 | + while True: |
| 110 | + result = allInstances.Next(1) |
| 111 | + instance = result[0] |
| 112 | + if not instance: |
| 113 | + break |
| 114 | + path = instance.GetInstallationPath() |
| 115 | + version = instance.GetInstallationVersion() |
| 116 | + instance2 = instance.QueryInterface(ISetupInstance2) |
| 117 | + packages = instance2.GetPackages() |
| 118 | + for package in packages: |
| 119 | + packageId = package.GetId() |
| 120 | + if packageId == 'Microsoft.VisualStudio.Component.VC.Tools.x86.x64': |
| 121 | + installs.append(path) |
| 122 | + return installs |
| 123 | + |
| 124 | +def GetInstalledVS2017WinSDKs(vs_path): |
| 125 | + sdks = [] |
| 126 | + has81sdk = False |
| 127 | + win8preg = re.compile(r"Microsoft.VisualStudio.Component.Windows81SDK") |
| 128 | + win10preg = re.compile(r"Microsoft.VisualStudio.Component.Windows10SDK.(\d+)") |
| 129 | + iface = CreateObject(GUID('{177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D}')) |
| 130 | + setupConfiguration = iface.QueryInterface(ISetupConfiguration2) |
| 131 | + allInstances = setupConfiguration.EnumAllInstances() |
| 132 | + while True: |
| 133 | + result = allInstances.Next(1) |
| 134 | + instance = result[0] |
| 135 | + if not instance: |
| 136 | + break |
| 137 | + path = instance.GetInstallationPath() |
| 138 | + if path != vs_path: |
| 139 | + continue |
| 140 | + instance2 = instance.QueryInterface(ISetupInstance2) |
| 141 | + packages = instance2.GetPackages() |
| 142 | + for package in packages: |
| 143 | + packageId = package.GetId() |
| 144 | + if win8preg.match(packageId): |
| 145 | + has81sdk = True |
| 146 | + else: |
| 147 | + win10match = win10preg.match(packageId) |
| 148 | + if win10match: |
| 149 | + sdks.append('10.0.' + str(win10match.group(1)) + '.0') |
| 150 | + |
| 151 | + sdks.sort(reverse = True) |
| 152 | + if has81sdk: |
| 153 | + sdks.append('8.1') |
| 154 | + return sdks |
| 155 | + |
| 156 | +def main(): |
| 157 | + if len(sys.argv) == 1: |
| 158 | + installs = GetVS2017CPPBasePath() |
| 159 | + if len(installs) == 0: |
| 160 | + return |
| 161 | + for install in installs: |
| 162 | + sdks = GetInstalledVS2017WinSDKs(install) |
| 163 | + if len(sdks) > 0: |
| 164 | + print install |
| 165 | + return |
| 166 | + print installs[0] |
| 167 | + else: |
| 168 | + sdks = GetInstalledVS2017WinSDKs(sys.argv[1]) |
| 169 | + if len(sdks) > 0: |
| 170 | + print sdks[0] |
| 171 | + |
| 172 | +if __name__ == '__main__': |
| 173 | + main() |
0 commit comments