mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 09:46:54 +02:00
[installer] Support per-user installation (#24087)
* Add per user installer
* Separate upgrade codes for per machine and per user installation
Move per machine check to bootstrapper
Move all defines to common.wxs
Fix CI
* Update installer/PowerToysSetup/generateFileList.ps1
Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
* Update installer/PowerToysSetup/generateAllFileComponents.ps1
Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
* Update installer/PowerToysSetup/generateFileList.ps1
Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
* expect.txt
* Revert "Update installer/PowerToysSetup/generateFileList.ps1"
This reverts commit 34545dab9c.
* Update release CI to build both installers
* Revert bundle name change
It messes up app ID for per-user installation which ends up breaking winget update
of the per-user PT
* spellcheck
* Fix bad merge
* Add RegistryPreview
* Include backup_restore_settings.json
* Revert testing endpoint change
---------
Co-authored-by: Jeremy Sinclair <4016293+snickler@users.noreply.github.com>
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
|
||||
#include <common/SettingsAPI/settings_helpers.h>
|
||||
#include <common/utils/json.h>
|
||||
#include <common/utils/registry.h>
|
||||
|
||||
using namespace registry::install_scope;
|
||||
|
||||
namespace // Strings in this namespace should not be localized
|
||||
{
|
||||
@@ -42,9 +45,16 @@ namespace updating
|
||||
std::pair<Uri, std::wstring> extract_installer_asset_download_info(const json::JsonObject& release_object)
|
||||
{
|
||||
const std::wstring_view required_architecture = get_architecture_string(get_current_architecture());
|
||||
constexpr const std::wstring_view required_filename_pattern = updating::INSTALLER_FILENAME_PATTERN;
|
||||
std::wstring_view required_filename_pattern = updating::INSTALLER_FILENAME_PATTERN;
|
||||
// Desc-sorted by its priority
|
||||
const std::array<std::wstring_view, 2> asset_extensions = { L".exe", L".msi" };
|
||||
|
||||
const InstallScope current_install_scope = get_current_install_scope();
|
||||
if (current_install_scope == InstallScope::PerUser)
|
||||
{
|
||||
required_filename_pattern = updating::INSTALLER_FILENAME_PATTERN_USER;
|
||||
}
|
||||
|
||||
for (const auto asset_extension : asset_extensions)
|
||||
{
|
||||
for (auto asset_elem : release_object.GetNamedArray(L"assets"))
|
||||
|
||||
@@ -31,4 +31,5 @@ namespace updating
|
||||
|
||||
// non-localized
|
||||
constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup";
|
||||
constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN_USER = L"powertoysusersetup";
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<PlatformToolset>v143</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="..\..\..\deps\spdlog.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
|
||||
@@ -12,14 +12,16 @@
|
||||
namespace // Strings in this namespace should not be localized
|
||||
{
|
||||
const inline wchar_t POWER_TOYS_UPGRADE_CODE[] = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
|
||||
const inline wchar_t POWER_TOYS_UPGRADE_CODE_USER[] = L"{D8B559DB-4C98-487A-A33F-50A8EEE42726}";
|
||||
const inline wchar_t POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
|
||||
}
|
||||
|
||||
std::optional<std::wstring> GetMsiPackageInstalledPath()
|
||||
std::optional<std::wstring> GetMsiPackageInstalledPath(bool perUser)
|
||||
{
|
||||
constexpr size_t guid_length = 39;
|
||||
wchar_t product_ID[guid_length];
|
||||
if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, product_ID); !found)
|
||||
std::wstring upgradeCode = (perUser ? POWER_TOYS_UPGRADE_CODE_USER : POWER_TOYS_UPGRADE_CODE);
|
||||
if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(upgradeCode.c_str(), 0, 0, product_ID); !found)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,83 @@
|
||||
|
||||
namespace registry
|
||||
{
|
||||
namespace install_scope
|
||||
{
|
||||
const wchar_t INSTALL_SCOPE_REG_KEY[] = L"Software\\Classes\\powertoys\\";
|
||||
|
||||
enum class InstallScope
|
||||
{
|
||||
PerMachine = 0,
|
||||
PerUser,
|
||||
};
|
||||
|
||||
inline const InstallScope get_current_install_scope()
|
||||
{
|
||||
// Open HKLM key
|
||||
HKEY perMachineKey{};
|
||||
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
|
||||
INSTALL_SCOPE_REG_KEY,
|
||||
0,
|
||||
KEY_READ,
|
||||
&perMachineKey) != ERROR_SUCCESS)
|
||||
{
|
||||
// Open HKCU key
|
||||
HKEY perUserKey{};
|
||||
if (RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
INSTALL_SCOPE_REG_KEY,
|
||||
0,
|
||||
KEY_READ,
|
||||
&perUserKey) != ERROR_SUCCESS)
|
||||
{
|
||||
// both keys are missing
|
||||
return InstallScope::PerMachine;
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD dataSize{};
|
||||
if (RegGetValueW(
|
||||
perUserKey,
|
||||
nullptr,
|
||||
L"InstallScope",
|
||||
RRF_RT_REG_SZ,
|
||||
nullptr,
|
||||
nullptr,
|
||||
&dataSize) != ERROR_SUCCESS)
|
||||
{
|
||||
// HKCU key is missing
|
||||
RegCloseKey(perUserKey);
|
||||
return InstallScope::PerMachine;
|
||||
}
|
||||
|
||||
std::wstring data;
|
||||
data.resize(dataSize / sizeof(wchar_t));
|
||||
|
||||
if (RegGetValueW(
|
||||
perUserKey,
|
||||
nullptr,
|
||||
L"InstallScope",
|
||||
RRF_RT_REG_SZ,
|
||||
nullptr,
|
||||
&data[0],
|
||||
&dataSize) != ERROR_SUCCESS)
|
||||
{
|
||||
// HKCU key is missing
|
||||
RegCloseKey(perUserKey);
|
||||
return InstallScope::PerMachine;
|
||||
}
|
||||
RegCloseKey(perUserKey);
|
||||
|
||||
if (data.contains(L"perUser"))
|
||||
{
|
||||
return InstallScope::PerUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return InstallScope::PerMachine;
|
||||
}
|
||||
}
|
||||
|
||||
template<class>
|
||||
inline constexpr bool always_false_v = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user