microsoft / vswhere

Locate Visual Studio 2017 and newer installations
MIT License
923 stars 98 forks source link

Python2 hangs calling vswhere since vs2022 update #312

Closed ddevienne closed 5 months ago

ddevienne commented 5 months ago

We have had for ages a Python2 script (Python 2.7.13 to be exact) using vswhere to locate Visual Studio. Was working fine on my machine with VS2017 and VS2019. But since installing VS2022, that script hangs. Neither the script nor Python changes. We've narrowed it down to subprocess.Popen() hanging. Here's the trace after a CTRL-C to get out of the hang:

D:\...\tools\BMS>python get_vs.py
Traceback (most recent call last):
  File "get_vs.py", line 4218, in <module>
    main(sys.argv)
  File "get_vs.py", line 4215, in main
    (build_env.vcvars, build_env.compiler) = get_vcvars(build_env.visual_studio_version)
  File "get_vs.py", line 107, in get_vcvars
    while process.poll() is None:
  File "C:\Python27\lib\subprocess.py", line 485, in poll
    return self._internal_poll()
  File "C:\Python27\lib\subprocess.py", line 679, in _internal_poll
    if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
KeyboardInterrupt

Somehow using -latest fixes the hang, but forces us to move to VS2022 unconditionally. Here's the relevant excerpt from the Python2 code that hangs:

def get_vcvars(visual_studio_version):
    vswhere_exe = r"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
    if not os.path.isfile(vswhere_exe):
        print("Error: vswhere not found at:\n    ", vswhere_exe)
        return None, None
    process = subprocess.Popen([vswhere_exe, "-nologo"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    while process.poll() is None:
        pass
    if process.returncode != 0:
        print("Error: vswhere utility did not returned with 0 code")
        return None, None
    instances = dict()
    last_instance = None
    for line in process.stdout:
        ...

What could have changed in vswhere to explain this behavior? We're at a complete loss to explain what we are seeing. Any idea?

heaths commented 5 months ago

vswhere does not block without -latest, so I'm not sure what's wrong but I also would not rely on the installed version. It can be quite old. For example, we did fix some UTF-8 output but that behavior was opt-in via the -utf8 flag. But the VS2017 and maybe VS2019 in-box versions don't have that. It should not be UTF-8 with -latest, though. We have regression tests for that and would've noticed.

-latest has been a flag since the first version, though. If you're checking for that yourself, you can use just -latest. I also recall that -property has been there since the first version, so if you want just the install path, for example, let vswhere do the work for you in native code as opposed to interpreted script e.g., vswhere -latest -property installationPath. You can also pass -format with a couple of flags like xml or json for easier processing.