@@ -115,18 +115,62 @@ def Exit( self ):
115115 'See the YCM docs for details on how to use a custom Clangd.' )
116116
117117
118- def FindLatestMSVC ():
119- import winreg
120- handle = winreg .ConnectRegistry (None , winreg .HKEY_LOCAL_MACHINE )
121- msvc = None
122- for i in [17 , 16 , 15 ]:
123- try :
124- winreg .OpenKey (handle , rf'SOFTWARE\Microsoft\VisualStudio\{ i } .0' )
125- msvc = i
126- break
127- except FileNotFoundError :
128- pass
129- return msvc
118+ def FindLatestMSVC (quiet ):
119+ ACCEPTABLE_VERSIONS = [17 , 16 , 15 ]
120+
121+ VSWHERE_EXE = os .path .join (os .environ ['ProgramFiles(x86)' ],
122+ 'Microsoft Visual Studio' ,
123+ 'Installer' , 'vswhere.exe' )
124+
125+ if os .path .exists (VSWHERE_EXE ):
126+ if not quiet :
127+ print ("Calling vswhere -latest -installationVersion" )
128+ latest_full_v = subprocess .check_output (
129+ [VSWHERE_EXE , '-latest' , '-property' , 'installationVersion' ]
130+ ).strip ().decode ()
131+ if '.' in latest_full_v :
132+ try :
133+ latest_v = int (latest_full_v .split ('.' )[0 ])
134+ except ValueError :
135+ raise ValueError ("{latest_full_v=} is not a version number." )
136+
137+ if not quiet :
138+ print (f'vswhere -latest returned version { latest_full_v = } ' )
139+
140+ if latest_v not in ACCEPTABLE_VERSIONS :
141+ if latest_v > 17 :
142+ if not quiet :
143+ print (f'MSVC Version { latest_full_v = } is newer than expected.' )
144+ else :
145+ raise ValueError (
146+ f'vswhere returned { latest_full_v = } which is unexpected.'
147+ 'Pass --msvc <version> argument.' )
148+ return latest_v
149+ else :
150+ if not quiet :
151+ print (f'vswhere returned nothing usable, { latest_full_v = } ' )
152+
153+ # Fall back to registry parsing, which works at least until MSVC 2019 (16)
154+ # but is likely failing on MSVC 2022 (17)
155+ if not quiet :
156+ print ("vswhere method failed, falling back to searching the registry" )
157+
158+ import winreg
159+ handle = winreg .ConnectRegistry (None , winreg .HKEY_LOCAL_MACHINE )
160+ msvc = None
161+ for i in ACCEPTABLE_VERSIONS :
162+ if not quiet :
163+ print ('Trying to find '
164+ rf'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\{ i } .0' )
165+ try :
166+ winreg .OpenKey (handle , rf'SOFTWARE\Microsoft\VisualStudio\{ i } .0' )
167+ if not quiet :
168+ print (f"Found MSVC version { i } " )
169+ msvc = i
170+ break
171+ except FileNotFoundError :
172+ pass
173+ return msvc
130174
131175
132176def RemoveDirectory ( directory ):
@@ -507,9 +551,9 @@ def ParseArguments():
507551 args .enable_debug = True
508552
509553 if OnWindows () and args .msvc is None :
510- args .msvc = FindLatestMSVC ()
554+ args .msvc = FindLatestMSVC (args . quiet )
511555 if args .msvc is None :
512- raise FileNotFoundError ("Could not find a valid MSVC version" )
556+ raise FileNotFoundError ("Could not find a valid MSVC version. " )
513557
514558 if args .core_tests :
515559 os .environ [ 'YCM_TESTRUN' ] = '1'
0 commit comments