diff --git a/src/lib/corelib/tools/msvcinfo.cpp b/src/lib/corelib/tools/msvcinfo.cpp index 973284b2b..daef94975 100644 --- a/src/lib/corelib/tools/msvcinfo.cpp +++ b/src/lib/corelib/tools/msvcinfo.cpp @@ -318,38 +318,71 @@ static QString vswhereFilePath() } enum class ProductType { VisualStudio, BuildTools }; +static QByteArray getVSWhereJsonOutput(ProductType productType, Logger &logger) +{ + auto chcpArgs = []() -> QStringList { + return {QStringLiteral("chcp"), QStringLiteral("65001")}; + }(); + + auto vswhereArgs = [productType, logger]() -> QStringList { + const QString vswhere = vswhereFilePath(); + if (vswhere.isEmpty()) { + logger.qbsWarning() << Tr::tr("The vswhere tool not found"); + return {}; + } + + QStringList args; + args << vswhere; + if (productType == ProductType::VisualStudio) { + args << QStringLiteral("-all") + << QStringLiteral("-legacy") + << QStringLiteral("-prerelease"); + } else { + args << QStringLiteral("-products") + << QStringLiteral("Microsoft.VisualStudio.Product.BuildTools"); + } + + args << QStringLiteral("-format") << QStringLiteral("json") << QStringLiteral("-utf8"); + return args; + }(); + + if (vswhereArgs.isEmpty()) + return {}; + + QStringList args; + args << QLatin1String("/c"); + args << chcpArgs; + args << QLatin1String(">$1"); + args << QLatin1String("&&"); + args << vswhereArgs; + QProcess cmd; + cmd.start(QLatin1String("cmd"), args); + if (!cmd.waitForStarted(-1)) + return {}; + if (!cmd.waitForFinished(-1)) { + logger.qbsWarning() << Tr::tr("The cmd tool failed to run: %1").arg(cmd.errorString()); + return {}; + } + if (cmd.exitCode() != 0) { + const QString stdOut = QString::fromLocal8Bit(cmd.readAllStandardOutput()); + const QString stdErr = QString::fromLocal8Bit(cmd.readAllStandardError()); + logger.qbsWarning() << Tr::tr("The cmd tool failed to run.\n%1").arg( + formatVswhereOutput(stdOut, stdErr)); + return {}; + } + + return cmd.readAllStandardOutput(); +} + static std::vector retrieveInstancesFromVSWhere( ProductType productType, Logger &logger) { + const auto output = getVSWhereJsonOutput(productType, logger); + if (output.isEmpty()) + return {}; std::vector result; - const QString cmd = vswhereFilePath(); - if (cmd.isEmpty()) - return result; - QProcess vsWhere; - QStringList args = productType == ProductType::VisualStudio - ? QStringList({QStringLiteral("-all"), QStringLiteral("-legacy"), - QStringLiteral("-prerelease")}) - : QStringList({QStringLiteral("-products"), - QStringLiteral("Microsoft.VisualStudio.Product.BuildTools")}); - args << QStringLiteral("-format") << QStringLiteral("json") << QStringLiteral("-utf8"); - vsWhere.start(cmd, args); - if (!vsWhere.waitForStarted(-1)) - return result; - if (!vsWhere.waitForFinished(-1)) { - logger.qbsWarning() << Tr::tr("The vswhere tool failed to run").append(QLatin1String(": ")) - .append(vsWhere.errorString()); - return result; - } - if (vsWhere.exitCode() != 0) { - const QString stdOut = QString::fromLocal8Bit(vsWhere.readAllStandardOutput()); - const QString stdErr = QString::fromLocal8Bit(vsWhere.readAllStandardError()); - logger.qbsWarning() << Tr::tr("The vswhere tool failed to run").append(QLatin1String(".\n")) - .append(formatVswhereOutput(stdOut, stdErr)); - return result; - } QJsonParseError parseError{}; - QJsonDocument jsonOutput = QJsonDocument::fromJson(vsWhere.readAllStandardOutput(), - &parseError); + QJsonDocument jsonOutput = QJsonDocument::fromJson(output, &parseError); if (parseError.error != QJsonParseError::NoError) { logger.qbsWarning() << Tr::tr("The vswhere tool produced invalid JSON output: %1") .arg(parseError.errorString());