terminal/src/cascadia/TerminalSettingsModel/VsSetupConfiguration.h
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

254 lines
9 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Licensed under the MIT license.
Module Name:
- VsSetupConfiguration
Abstract:
- Encapsulates the Visual Studio Setup Configuration COM APIs
Author(s):
- Charles Willis - October 2020
- Heath Stewart - September 2021
--*/
#pragma once
#include "Setup.Configuration.h"
namespace winrt::Microsoft::Terminal::Settings::Model
{
/// <summary>
/// See https://docs.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.setup.configuration?view=visualstudiosdk-2019
/// </summary>
class VsSetupConfiguration
{
typedef wil::com_ptr<ISetupConfiguration2> ComPtrSetupQuery;
typedef wil::com_ptr<ISetupHelper> ComPtrSetupHelper;
typedef wil::com_ptr<ISetupInstance> ComPtrSetupInstance;
typedef wil::com_ptr<ISetupInstance2> ComPtrSetupInstance2;
typedef wil::com_ptr<ISetupPropertyStore> ComPtrPropertyStore;
typedef wil::com_ptr<ISetupPackageReference> ComPtrPackageReference;
typedef wil::com_ptr<ISetupInstanceCatalog> ComPtrInstanceCatalog;
typedef ComPtrPropertyStore ComPtrCustomPropertyStore;
typedef ComPtrPropertyStore ComPtrCatalogPropertyStore;
public:
struct VsSetupInstance
{
VsSetupInstance(VsSetupInstance&& other) = default;
VsSetupInstance& operator=(VsSetupInstance&&) = default;
std::wstring ResolvePath(std::wstring_view relativePath) const
{
return VsSetupConfiguration::ResolvePath(inst.get(), relativePath);
}
bool VersionInRange(std::wstring_view range) const
{
return InstallationVersionInRange(query.get(), inst.get(), range);
}
std::wstring GetVersion() const
{
return VsSetupConfiguration::GetInstallationVersion(inst.get());
}
unsigned long long GetComparableInstallDate() const noexcept
{
return installDate;
}
unsigned long long GetComparableVersion() const noexcept
{
return version;
}
std::wstring GetInstallationPath() const
{
return VsSetupConfiguration::GetInstallationPath(inst.get());
}
std::wstring GetInstanceId() const
{
return VsSetupConfiguration::GetInstanceId(inst.get());
}
ComPtrPropertyStore GetInstancePropertyStore() const
{
ComPtrPropertyStore properties;
inst.query_to<ISetupPropertyStore>(&properties);
return properties;
}
ComPtrCustomPropertyStore GetCustomPropertyStore() const
{
ComPtrSetupInstance2 instance2;
inst.query_to<ISetupInstance2>(&instance2);
ComPtrCustomPropertyStore properties;
if (FAILED(instance2->GetProperties(&properties)))
{
return nullptr;
}
return properties;
}
ComPtrCatalogPropertyStore GetCatalogPropertyStore() const
{
ComPtrInstanceCatalog instanceCatalog;
inst.query_to<ISetupInstanceCatalog>(&instanceCatalog);
ComPtrCatalogPropertyStore properties;
if (FAILED(instanceCatalog->GetCatalogInfo(&properties)))
{
return nullptr;
}
return properties;
}
std::wstring GetProfileNameSuffix() const
{
return profileNameSuffix;
}
VsSetupInstance(ComPtrSetupQuery pQuery, ComPtrSetupInstance pInstance) :
query(pQuery), // Copy and AddRef the query object.
inst(std::move(pInstance)), // Take ownership of the instance object.
profileNameSuffix(BuildProfileNameSuffix()),
installDate(GetInstallDate()),
version(GetInstallationVersion())
{
}
private:
ComPtrSetupQuery query;
ComPtrSetupInstance inst;
std::wstring profileNameSuffix;
// Cache oft-accessed properties used in sorting.
unsigned long long installDate;
unsigned long long version;
std::wstring BuildProfileNameSuffix() const
{
ComPtrCatalogPropertyStore catalogProperties = GetCatalogPropertyStore();
if (catalogProperties != nullptr)
{
std::wstring suffix;
std::wstring productLine{ GetProductLineVersion(catalogProperties.get()) };
suffix.append(productLine);
ComPtrCustomPropertyStore customProperties = GetCustomPropertyStore();
if (customProperties != nullptr)
{
std::wstring nickname{ GetNickname(customProperties.get()) };
if (!nickname.empty())
{
suffix.append(L" (" + nickname + L")");
}
else
{
ComPtrPropertyStore instanceProperties = GetInstancePropertyStore();
suffix.append(GetChannelNameSuffixTag(instanceProperties.get()));
}
}
else
{
ComPtrPropertyStore instanceProperties = GetInstancePropertyStore();
suffix.append(GetChannelNameSuffixTag(instanceProperties.get()));
}
return suffix;
}
return GetVersion();
}
unsigned long long GetInstallDate() const
{
return VsSetupConfiguration::GetInstallDate(inst.get());
}
unsigned long long GetInstallationVersion() const
{
const auto helper = wil::com_query<ISetupHelper>(query);
std::wstring versionString{ GetVersion() };
unsigned long long version{ 0 };
THROW_IF_FAILED(helper->ParseVersion(versionString.data(), &version));
return version;
}
static std::wstring GetChannelNameSuffixTag(ISetupPropertyStore* instanceProperties)
{
std::wstring tag;
std::wstring channelName{ GetChannelName(instanceProperties) };
if (channelName.empty())
{
return channelName;
}
if (channelName != L"Release")
{
tag.append(L" [" + channelName + L"]");
}
return tag;
}
static std::wstring GetChannelId(ISetupPropertyStore* instanceProperties)
{
return GetStringProperty(instanceProperties, L"channelId");
}
static std::wstring GetChannelName(ISetupPropertyStore* instanceProperties)
{
std::wstring channelId{ GetChannelId(instanceProperties) };
if (channelId.empty())
{
return channelId;
}
std::wstring channelName;
// channelId is in the format <ProductName>.<MajorVersion>.<ChannelName>
size_t pos = channelId.rfind(L".");
if (pos != std::wstring::npos)
{
channelName.append(channelId.substr(pos + 1));
}
return channelName;
}
static std::wstring GetNickname(ISetupPropertyStore* customProperties)
{
return GetStringProperty(customProperties, L"nickname");
}
static std::wstring GetProductLineVersion(ISetupPropertyStore* customProperties)
{
return GetStringProperty(customProperties, L"productLineVersion");
}
};
static std::vector<VsSetupInstance> QueryInstances();
private:
static bool InstallationVersionInRange(ISetupConfiguration2* pQuery, ISetupInstance* pInst, std::wstring_view range);
static std::wstring ResolvePath(ISetupInstance* pInst, std::wstring_view relativePath);
static std::wstring GetInstallationVersion(ISetupInstance* pInst);
static std::wstring GetInstallationPath(ISetupInstance* pInst);
static std::wstring GetInstanceId(ISetupInstance* pInst);
static unsigned long long GetInstallDate(ISetupInstance* pInst);
static std::wstring GetStringProperty(ISetupPropertyStore* pProps, std::wstring_view name);
};
};