Skip to content

Commit

Permalink
Modify vshwere() to work with old versions that don't support -utf8.
Browse files Browse the repository at this point in the history
Fall back to trying to decode with the current Windows codepage.
  • Loading branch information
lewissbaker committed Aug 13, 2018
1 parent a8fafef commit bd492ab
Showing 1 changed file with 81 additions and 10 deletions.
91 changes: 81 additions & 10 deletions src/cake/msvs.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
import json
import os
import subprocess
import _winreg as winreg
import _winreg as winreg
import codecs

import cake.path
import cake.system
Expand Down Expand Up @@ -161,7 +162,57 @@ def getDotNetFrameworkSdkDir(version='2.0'):
subKey = r"SOFTWARE\Microsoft\.NETFramework"
valueName = "sdkInstallRootv" + version
return queryString(winreg.HKEY_LOCAL_MACHINE, subKey, valueName)


try:
import ctypes
import ctypes.wintypes

_GetConsoleOutputCP = ctypes.windll.kernel32.GetConsoleOutputCP
_GetConsoleOutputCP.argtypes = []
_GetConsoleOutputCP.restype = ctypes.wintypes.UINT

# Constructed from translating between:
# https://docs.microsoft.com/en-gb/windows/desktop/Intl/code-page-identifiers
# and
# https://docs.python.org/2.4/lib/standard-encodings.html
_codepageToCodec = {
950 : "big5",
1200 : "utf_16_le",
1201 : "utf_16_be",
12000 : "utf_32_le",
12001 : "utf_32_be",
20127 : "us-ascii",
28591 : "latin_1",
28592 : "iso8859_2",
28593 : "iso8859_3",
28594 : "iso8859_4",
28595 : "iso8859_5",
28596 : "iso8859_6",
28597 : "iso8859_7",
28598 : "iso8859_8",
28599 : "iso8859_9",
28603 : "iso8859_13",
28605 : "iso8859_15",
65000 : "utf_7",
65001 : "utf_8",
}

def _getCodecFromCodepage():
codepage = _GetConsoleOutputCP()
codecName = _codepageToCodec.get(codepage, None)
if codecName is None:
codecName = "cp{0:03}".format(codepage)

try:
return codecs.lookup(codecName)
except LookupError:
return None

except Exception:

def _getCodecFromCodepage():
return None

def vswhere(args=[]):
"""Helper function for running vswhere helper utility and parsing the output.
Expand All @@ -172,7 +223,7 @@ def vswhere(args=[]):
@raise EnvironmentError:
If there was a problem running vswhere with the provided arguments.
"""
"""
if cake.system.isWindows64():
programFiles = os.environ.get('ProgramFiles(x86)', r'C:\Program Files (x86)')
else:
Expand All @@ -181,18 +232,38 @@ def vswhere(args=[]):
vsWherePath = cake.path.join(vsInstaller, 'vswhere.exe')
if not os.path.isfile(vsWherePath):
raise EnvironmentError("vswhere not found at " + vsWherePath)


p = subprocess.Popen(
args=["vswhere", "-format", "json", "-utf8"] + args,
executable=vsWherePath,
cwd=vsInstaller,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE,
)
out, err = p.communicate(input=b"")

if p.returncode != 0:
raise EnvironmentError("vswhere: returned with exit code " + str(p.returncode) + "\n" + out)
)
out, err = p.communicate(input=b"")
codec = codecs.lookup("utf_8")

return json.loads(out.decode("utf8"))
if p.returncode != 0:
# Probably failed because it's an old version of vswhere that doesn't support
# -utf8 flag. Let's try using it without -utf8 and then use whatever the current
# Windows codepage is to decode it.
p = subprocess.Popen(
args=["vswhere", "-format", "json"] + args,
executable=vsWherePath,
cwd=vsInstaller,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
stdin=subprocess.PIPE,
)
out, err = p.communicate(input=b"")
codec = _getCodecFromCodepage()
if codec is None:
# Fall back to ASCII if we couldn't figure out the codec for
# the current Windows codepage.
codec = codecs.lookup("ascii")

if p.returncode != 0:
raise EnvironmentError("vswhere: returned with exit code " + str(p.returncode) + "\n" + out)

return json.loads(codec.decode(out, 'replace')[0])

0 comments on commit bd492ab

Please sign in to comment.