terminal/src/cascadia/TerminalSettingsModel/VsSetupConfiguration.cpp
Leonard Hecker 5a23029dac
Further reduce number of generated VS profiles (#11489)
This commit reduces the number of generated VS profiles from 6 down to just 2
per VS instance. The reason we did this is out of concern of overwhelming or
annoying new users with too many profiles. Especially since it's far easier
at the moment to add new generators compared to removing them.

As before only the latest instance is not hidden by default.

## PR Checklist
* [x] I work here
* [x] Tests added/passed
* [x] As discussed in a Team Sync meeting

## Validation Steps Performed
* Installed Visual Studio 2019 and 2022 Preview
* A profile for both is generated, while the 2019 one is hidden by default ✔️
* $env:VSCMD_ARG_TGT_ARCH is x64 on my AMD64 machine ✔️
2021-10-19 23:52:00 +00:00

127 lines
4.4 KiB
C++

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "VsSetupConfiguration.h"
using namespace winrt::Microsoft::Terminal::Settings::Model;
std::vector<VsSetupConfiguration::VsSetupInstance> VsSetupConfiguration::QueryInstances()
{
std::vector<VsSetupInstance> instances;
// SetupConfiguration is only registered if Visual Studio is installed
ComPtrSetupQuery pQuery{ wil::CoCreateInstanceNoThrow<SetupConfiguration, ISetupConfiguration2>() };
if (pQuery == nullptr)
{
return instances;
}
// Enumerate all valid instances of Visual Studio
wil::com_ptr<IEnumSetupInstances> e;
THROW_IF_FAILED(pQuery->EnumInstances(&e));
for (ComPtrSetupInstance rgpInstance; S_OK == THROW_IF_FAILED(e->Next(1, &rgpInstance, nullptr));)
{
instances.emplace_back(pQuery, std::move(rgpInstance));
}
// Sort instances based on version and install date from latest to oldest.
std::sort(instances.begin(), instances.end(), [](const VsSetupInstance& a, const VsSetupInstance& b) {
auto const aVersion = a.GetComparableVersion();
auto const bVersion = b.GetComparableVersion();
if (aVersion == bVersion)
{
return a.GetComparableInstallDate() > b.GetComparableInstallDate();
}
return aVersion > bVersion;
});
return instances;
}
/// <summary>
/// Takes a relative path under a Visual Studio installation and returns the absolute path.
/// </summary>
std::wstring VsSetupConfiguration::ResolvePath(ISetupInstance* pInst, std::wstring_view relativePath)
{
wil::unique_bstr bstrAbsolutePath;
THROW_IF_FAILED(pInst->ResolvePath(relativePath.data(), &bstrAbsolutePath));
return bstrAbsolutePath.get();
}
/// <summary>
/// Determines whether a Visual Studio installation version falls within a specified range.
/// The range is specified as a string, ex: "[15.0.0.0,)", "[15.0.0.0, 16.7.0.0)
/// </summary>
bool VsSetupConfiguration::InstallationVersionInRange(ISetupConfiguration2* pQuery, ISetupInstance* pInst, std::wstring_view range)
{
const auto helper = wil::com_query<ISetupHelper>(pQuery);
// VS versions in a string format such as "16.3.0.0" can be easily compared
// by parsing them into 64-bit unsigned integers using the stable algorithm
// provided by ParseVersion and ParseVersionRange
unsigned long long minVersion{ 0 };
unsigned long long maxVersion{ 0 };
THROW_IF_FAILED(helper->ParseVersionRange(range.data(), &minVersion, &maxVersion));
wil::unique_bstr bstrVersion;
THROW_IF_FAILED(pInst->GetInstallationVersion(&bstrVersion));
unsigned long long ullVersion{ 0 };
THROW_IF_FAILED(helper->ParseVersion(bstrVersion.get(), &ullVersion));
return ullVersion >= minVersion && ullVersion <= maxVersion;
}
std::wstring VsSetupConfiguration::GetInstallationVersion(ISetupInstance* pInst)
{
wil::unique_bstr bstrInstallationVersion;
THROW_IF_FAILED(pInst->GetInstallationVersion(&bstrInstallationVersion));
return bstrInstallationVersion.get();
}
std::wstring VsSetupConfiguration::GetInstallationPath(ISetupInstance* pInst)
{
wil::unique_bstr bstrInstallationPath;
THROW_IF_FAILED(pInst->GetInstallationPath(&bstrInstallationPath));
return bstrInstallationPath.get();
}
/// <summary>
/// The instance id is unique for each Visual Studio installation on a system.
/// The instance id is generated by the Visual Studio setup engine and varies from system to system.
/// </summary>
std::wstring VsSetupConfiguration::GetInstanceId(ISetupInstance* pInst)
{
wil::unique_bstr bstrInstanceId;
THROW_IF_FAILED(pInst->GetInstanceId(&bstrInstanceId));
return bstrInstanceId.get();
}
unsigned long long VsSetupConfiguration::GetInstallDate(ISetupInstance* pInst)
{
FILETIME ftInstallDate{ 0 };
THROW_IF_FAILED(pInst->GetInstallDate(&ftInstallDate));
return wil::filetime::to_int64(ftInstallDate);
}
std::wstring VsSetupConfiguration::GetStringProperty(ISetupPropertyStore* pProps, std::wstring_view name)
{
if (pProps == nullptr)
{
return std::wstring{};
}
wil::unique_variant var;
if (FAILED(pProps->GetValue(name.data(), &var)) || var.vt != VT_BSTR)
{
return std::wstring{};
}
return var.bstrVal;
}