diff --git a/.pipelines/pipeline.user.windows.yml b/.pipelines/pipeline.user.windows.yml index a87d40cf9..27c6b3beb 100644 --- a/.pipelines/pipeline.user.windows.yml +++ b/.pipelines/pipeline.user.windows.yml @@ -65,6 +65,7 @@ build: to: 'Build_Output' include: - 'PowerToys.ActionRunner.exe' + - 'PowerToys.Update.exe' - 'BackgroundActivatorDLL.dll' - 'Notifications.dll' - 'os-detection.dll' diff --git a/PowerToys.sln b/PowerToys.sln index de55865c0..6ccb0cab0 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -272,8 +272,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "interop", "interop", "{5A78 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "log", "log", "{E4E03FE0-94FD-47C7-88C5-F17D0AA549D3}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinStore", "src\common\WinStore\Winstore.vcxproj", "{C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "COMUtils", "src\common\COMUtils\COMUtils.vcxproj", "{7319089E-46D6-4400-BC65-E39BDF1416EE}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Display", "src\common\Display\Display.vcxproj", "{CABA8DFB-823B-4BF2-93AC-3F31984150D9}" @@ -288,8 +286,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "utils", "utils", "{B39DC643 src\common\utils\EventLocker.h = src\common\utils\EventLocker.h src\common\utils\EventWaiter.h = src\common\utils\EventWaiter.h src\common\utils\exec.h = src\common\utils\exec.h + src\common\utils\HttpClient.h = src\common\utils\HttpClient.h src\common\utils\json.h = src\common\utils\json.h src\common\utils\logger_helper.h = src\common\utils\logger_helper.h + src\common\utils\MsiUtils.h = src\common\utils\MsiUtils.h src\common\utils\os-detect.h = src\common\utils\os-detect.h src\common\utils\process_path.h = src\common\utils\process_path.h src\common\utils\ProcessWaiter.h = src\common\utils\ProcessWaiter.h @@ -345,6 +345,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuideModuleInterfac EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShortcutGuide", "src\modules\ShortcutGuide\ShortcutGuide\ShortcutGuide.vcxproj", "{2EDB3EB4-FA92-4BFF-B2D8-566584837231}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToys.Update", "src\Update\PowerToys.Update.vcxproj", "{44CE9AE1-4390-42C5-BACC-0FD6B40AA203}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.PowerToys.Run.Plugin.WindowsSettings", "src\modules\launcher\Plugins\Microsoft.PowerToys.Run.Plugin.WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.csproj", "{5043CECE-E6A7-4867-9CBE-02D27D83747A}" EndProject Global @@ -623,10 +625,6 @@ Global {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64 {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64 {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Debug|x64.ActiveCfg = Debug|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Debug|x64.Build.0 = Debug|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Release|x64.ActiveCfg = Release|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Release|x64.Build.0 = Release|x64 {7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.ActiveCfg = Debug|x64 {7319089E-46D6-4400-BC65-E39BDF1416EE}.Debug|x64.Build.0 = Debug|x64 {7319089E-46D6-4400-BC65-E39BDF1416EE}.Release|x64.ActiveCfg = Release|x64 @@ -679,22 +677,22 @@ Global {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Debug|x64.Build.0 = Debug|x64 {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.ActiveCfg = Release|x64 {62173D9A-6724-4C00-A1C8-FB646480A9EC}.Release|x64.Build.0 = Release|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.ActiveCfg = Debug|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.Build.0 = Debug|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.ActiveCfg = Release|x64 - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.Build.0 = Release|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.ActiveCfg = Debug|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.Build.0 = Debug|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.ActiveCfg = Release|x64 - {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.Build.0 = Release|x64 {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.ActiveCfg = Debug|x64 {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Debug|x64.Build.0 = Debug|x64 {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.ActiveCfg = Release|x64 {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4}.Release|x64.Build.0 = Release|x64 + {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.ActiveCfg = Debug|x64 + {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Debug|x64.Build.0 = Debug|x64 + {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.ActiveCfg = Release|x64 + {5E7360A8-D048-4ED3-8F09-0BFD64C5529A}.Release|x64.Build.0 = Release|x64 {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.ActiveCfg = Debug|x64 {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Debug|x64.Build.0 = Debug|x64 {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.ActiveCfg = Release|x64 {3E424AD2-19E5-4AE6-B833-F53963EB5FC1}.Release|x64.Build.0 = Release|x64 + {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.ActiveCfg = Debug|x64 + {D940E07F-532C-4FF3-883F-790DA014F19A}.Debug|x64.Build.0 = Debug|x64 + {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.ActiveCfg = Release|x64 + {D940E07F-532C-4FF3-883F-790DA014F19A}.Release|x64.Build.0 = Release|x64 {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.ActiveCfg = Debug|x64 {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Debug|x64.Build.0 = Debug|x64 {2D604C07-51FC-46BB-9EB7-75AECC7F5E81}.Release|x64.ActiveCfg = Release|x64 @@ -703,6 +701,10 @@ Global {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Debug|x64.Build.0 = Debug|x64 {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.ActiveCfg = Release|x64 {2EDB3EB4-FA92-4BFF-B2D8-566584837231}.Release|x64.Build.0 = Release|x64 + {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.ActiveCfg = Debug|x64 + {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Debug|x64.Build.0 = Debug|x64 + {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.ActiveCfg = Release|x64 + {44CE9AE1-4390-42C5-BACC-0FD6B40AA203}.Release|x64.Build.0 = Release|x64 {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.ActiveCfg = Debug|x64 {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Debug|x64.Build.0 = Debug|x64 {5043CECE-E6A7-4867-9CBE-02D27D83747A}.Release|x64.ActiveCfg = Release|x64 @@ -789,7 +791,6 @@ Global {CC6E41AC-8174-4E8A-8D22-85DD7F4851DF} = {1AFB6476-670D-4E80-A464-657E01DFF482} {5A7818A8-109C-4E1C-850D-1A654E234B0E} = {1AFB6476-670D-4E80-A464-657E01DFF482} {E4E03FE0-94FD-47C7-88C5-F17D0AA549D3} = {1AFB6476-670D-4E80-A464-657E01DFF482} - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6} = {1AFB6476-670D-4E80-A464-657E01DFF482} {7319089E-46D6-4400-BC65-E39BDF1416EE} = {1AFB6476-670D-4E80-A464-657E01DFF482} {CABA8DFB-823B-4BF2-93AC-3F31984150D9} = {1AFB6476-670D-4E80-A464-657E01DFF482} {98537082-0FDB-40DE-ABD8-0DC5A4269BAB} = {1AFB6476-670D-4E80-A464-657E01DFF482} @@ -806,8 +807,8 @@ Global {23D2070D-E4AD-4ADD-85A7-083D9C76AD49} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} {62173D9A-6724-4C00-A1C8-FB646480A9EC} = {38BDB927-829B-4C65-9CD9-93FB05D66D65} {127F38E0-40AA-4594-B955-5616BF206882} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} - {5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {127F38E0-40AA-4594-B955-5616BF206882} {BB23A474-5058-4F75-8FA3-5FE3DE53CDF4} = {4AFC9975-2456-4C70-94A4-84073C1CED93} + {5E7360A8-D048-4ED3-8F09-0BFD64C5529A} = {127F38E0-40AA-4594-B955-5616BF206882} {3E424AD2-19E5-4AE6-B833-F53963EB5FC1} = {4AFC9975-2456-4C70-94A4-84073C1CED93} {D940E07F-532C-4FF3-883F-790DA014F19A} = {127F38E0-40AA-4594-B955-5616BF206882} {106CBECA-0701-4FC3-838C-9DF816A19AE2} = {4574FDD0-F61D-4376-98BF-E5A1262C11EC} diff --git a/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln b/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln index 2096d0c9a..8f2533645 100644 --- a/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln +++ b/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln @@ -3,8 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30320.27 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Updating", "..\..\src\common\updating\updating.vcxproj", "{17DA04DF-E393-4397-9CF0-84DABE11032E}" -EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "bootstrapper", "bootstrapper\bootstrapper.vcxproj", "{D194E3AA-F824-4CA9-9A58-034DD6B7D022}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\..\src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}" @@ -13,20 +11,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\..\src\common EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SetttingsAPI", "..\..\src\common\SettingsAPI\SetttingsAPI.vcxproj", "{6955446D-23F7-4023-9BB3-8657F904AF99}" EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Notifications", "..\..\src\common\notifications\notifications.vcxproj", "{1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WinStore", "..\..\src\common\WinStore\Winstore.vcxproj", "{C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.ActiveCfg = Debug|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Debug|x64.Build.0 = Debug|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.ActiveCfg = Release|x64 - {17DA04DF-E393-4397-9CF0-84DABE11032E}.Release|x64.Build.0 = Release|x64 {D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Debug|x64.ActiveCfg = Debug|x64 {D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Debug|x64.Build.0 = Debug|x64 {D194E3AA-F824-4CA9-9A58-034DD6B7D022}.Release|x64.ActiveCfg = Release|x64 @@ -43,14 +33,6 @@ Global {6955446D-23F7-4023-9BB3-8657F904AF99}.Debug|x64.Build.0 = Debug|x64 {6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.ActiveCfg = Release|x64 {6955446D-23F7-4023-9BB3-8657F904AF99}.Release|x64.Build.0 = Release|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.ActiveCfg = Debug|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Debug|x64.Build.0 = Debug|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.ActiveCfg = Release|x64 - {1D5BE09D-78C0-4FD7-AF00-AE7C1AF7C525}.Release|x64.Build.0 = Release|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Debug|x64.ActiveCfg = Debug|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Debug|x64.Build.0 = Debug|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Release|x64.ActiveCfg = Release|x64 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/common/updating/dotnet_installation.cpp b/installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.cpp similarity index 95% rename from src/common/updating/dotnet_installation.cpp rename to installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.cpp index 30cdd9697..7647dc143 100644 --- a/src/common/updating/dotnet_installation.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.cpp @@ -1,11 +1,10 @@ #include "pch.h" -#include "dotnet_installation.h" -#include "http_client.h" - -#include "utils/exec.h" -#include "utils/winapi_error.h" +#include "DotnetInstallation.h" +#include +#include +#include namespace fs = std::filesystem; namespace updating diff --git a/src/common/updating/dotnet_installation.h b/installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.h similarity index 100% rename from src/common/updating/dotnet_installation.h rename to installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.h diff --git a/installer/PowerToysBootstrapper/bootstrapper/Resources.resx b/installer/PowerToysBootstrapper/bootstrapper/Resources.resx index ce29162af..85368cc46 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/Resources.resx +++ b/installer/PowerToysBootstrapper/bootstrapper/Resources.resx @@ -67,30 +67,9 @@ PowerToys installation error - - An update to PowerToys is available. - - - Update now - - - Error: please uninstall the previous version of PowerToys manually. - An update to PowerToys is available. Visit our GitHub page to update. - - More info... - - - PowerToys Update - - - We've detected a previous installation of PowerToys. Would you like to remove it? - - - PowerToys: uninstall previous version? - Couldn't extract MSI installer. diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index 02eb38102..4420fed78 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -2,23 +2,21 @@ #include "Generated Files/resource.h" #include "RcResource.h" -#include -#include -#include +#include #include #include #include +#include +#include #include #include #include #include #include -#include - +#include "DotnetInstallation.h" #include "progressbar_window.h" -auto Strings = create_notifications_strings(); static bool g_Silent = false; #define STR_HELPER(x) #x @@ -95,7 +93,7 @@ void CleanupSettingsFromOlderVersions() spdlog::info("Old log settings file wasn't found"); } } - catch(...) + catch (...) { spdlog::error("Failed to cleanup old log settings"); } @@ -106,9 +104,9 @@ void ShowMessageBoxError(const wchar_t* message) if (!g_Silent) { MessageBoxW(nullptr, - message, - GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), - MB_OK | MB_ICONERROR); + message, + GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), + MB_OK | MB_ICONERROR); } } @@ -117,6 +115,46 @@ void ShowMessageBoxError(const UINT messageId) ShowMessageBoxError(GET_RESOURCE_STRING(messageId).c_str()); } +bool uninstall_msi_version(const std::wstring& package_path) +{ + const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); + return ERROR_SUCCESS == uninstall_result; +} + +std::optional get_installed_powertoys_version() +{ + auto installed_path = GetMsiPackageInstalledPath(); + if (!installed_path) + { + return std::nullopt; + } + *installed_path += L"\\PowerToys.exe"; + + // Get the version information for the file requested + const DWORD fvSize = GetFileVersionInfoSizeW(installed_path->c_str(), nullptr); + if (!fvSize) + { + return std::nullopt; + } + + auto pbVersionInfo = std::make_unique(fvSize); + + if (!GetFileVersionInfoW(installed_path->c_str(), 0, fvSize, pbVersionInfo.get())) + { + return std::nullopt; + } + + VS_FIXEDFILEINFO* fileInfo = nullptr; + UINT fileInfoLen = 0; + if (!VerQueryValueW(pbVersionInfo.get(), L"\\", reinterpret_cast(&fileInfo), &fileInfoLen)) + { + return std::nullopt; + } + return VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff, + (fileInfo->dwFileVersionMS >> 0) & 0xffff, + (fileInfo->dwFileVersionLS >> 16) & 0xffff }; +} + int Bootstrapper(HINSTANCE hInstance) { winrt::init_apartment(); @@ -133,17 +171,17 @@ int Bootstrapper(HINSTANCE hInstance) cxxopts::Options options{ "PowerToysBootstrapper" }; // clang-format off - options.add_options() - ("h,help", "Show help") - ("no_full_ui", "Use reduced UI for MSI") - ("s,silent", "Suppress all UI, notifications and does not start PowerToys") - ("no_start_pt", "Do not launch PowerToys after the installation is complete") - ("start_pt", "Always launch PowerToys after the installation is complete") - ("skip_dotnet_install", "Skip dotnet 3.X installation even if it's not detected") - ("log_level", "Log level. Possible values: off|debug|error", cxxopts::value()->default_value("off")) - ("log_dir", "Log directory", cxxopts::value()->default_value(".")) - ("install_dir", "Installation directory", cxxopts::value()->default_value(defaultInstallDir)) - ("extract_msi", "Extract MSI to the working directory and exit. Use only if you must access MSI directly."); + options.add_options() + ("h,help", "Show help") + ("no_full_ui", "Use reduced UI for MSI") + ("s,silent", "Suppress all UI, notifications and does not start PowerToys") + ("no_start_pt", "Do not launch PowerToys after the installation is complete") + ("start_pt", "Always launch PowerToys after the installation is complete") + ("skip_dotnet_install", "Skip dotnet 3.X installation even if it's not detected") + ("log_level", "Log level. Possible values: off|debug|error", cxxopts::value()->default_value("off")) + ("log_dir", "Log directory", cxxopts::value()->default_value(".")) + ("install_dir", "Installation directory", cxxopts::value()->default_value(defaultInstallDir)) + ("extract_msi", "Extract MSI to the working directory and exit. Use only if you must access MSI directly."); // clang-format on cxxopts::ParseResult cmdArgs; @@ -234,15 +272,15 @@ int Bootstrapper(HINSTANCE hInstance) const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); // Do not support installing on Windows < 1903 - if (updating::is_1809_or_older()) + if (!Is19H1OrHigher()) { - ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR); - spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString()); - return 1; + ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR); + spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString()); + return 1; } // Check if there's a newer version installed - const auto installedVersion = updating::get_installed_powertoys_version(); + const auto installedVersion = get_installed_powertoys_version(); if (installedVersion && *installedVersion >= myVersion) { spdlog::error(L"Detected a newer version {} vs {}", (*installedVersion).toWstring(), myVersion.toWstring()); @@ -341,7 +379,7 @@ int Bootstrapper(HINSTANCE hInstance) }); spdlog::debug("Acquiring existing MSI package path if exists"); - const auto package_path = updating::get_msi_package_path(); + const auto package_path = GetMsiPackagePath(); if (!package_path.empty()) { spdlog::debug(L"Existing MSI package path found: {}", package_path); @@ -351,7 +389,7 @@ int Bootstrapper(HINSTANCE hInstance) spdlog::debug("Existing MSI package path not found"); } - if (!package_path.empty() && !updating::uninstall_msi_version(package_path, Strings)) + if (!package_path.empty() && !uninstall_msi_version(package_path)) { spdlog::error("Couldn't install the existing MSI package ({})", GetLastError()); ShowMessageBoxError(IDS_UNINSTALL_PREVIOUS_VERSION_ERROR); @@ -401,7 +439,7 @@ int Bootstrapper(HINSTANCE hInstance) spdlog::error("Unknown exception during dotnet installation"); ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR); } - + // At this point, there's no reason to show progress bar window, since MSI installers have their own CloseProgressBarDialog(); @@ -419,7 +457,7 @@ int Bootstrapper(HINSTANCE hInstance) if ((!noStartPT && !g_Silent) || startPT) { spdlog::debug("Starting the newly installed PowerToys.exe"); - auto newPTPath = updating::get_msi_package_installed_path(); + auto newPTPath = GetMsiPackageInstalledPath(); if (!newPTPath) { spdlog::error("Couldn't determine new MSI package install location ({})", GetLastError()); @@ -448,7 +486,7 @@ int WINAPI WinMain(HINSTANCE hi, HINSTANCE, LPSTR, int) std::string messageA{ "Unhandled std exception encountered\n" }; messageA.append(ex.what()); - spdlog::error(messageA.c_str()); + spdlog::error(messageA.c_str()); std::wstring messageW{}; std::copy(messageA.begin(), messageA.end(), messageW.begin()); diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj index 1da5c3c2b..0b034d3e6 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj @@ -24,7 +24,9 @@ 16.0 {D194E3AA-F824-4CA9-9A58-034DD6B7D022} bootstrapper - 10.0.17134.0 + true + 10.0.18362.0 + 10.0.18362.0 bootstrapper @@ -71,7 +73,7 @@ - Level4 + Level3 true true true @@ -88,12 +90,12 @@ true true true - WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;%(AdditionalDependencies) + WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;Version.lib;%(AdditionalDependencies) - Level4 + Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDebug @@ -106,11 +108,12 @@ Windows true - WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;%(AdditionalDependencies) + WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;Version.lib;%(AdditionalDependencies) + Create Create @@ -119,6 +122,7 @@ + @@ -133,8 +137,11 @@ - - {17da04df-e393-4397-9cf0-84dabe11032e} + + {6955446d-23f7-4023-9bb3-8657f904af99} + + + {cc6e41ac-8174-4e8a-8d22-85dd7f4851df} {7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f} diff --git a/installer/PowerToysBootstrapper/bootstrapper/pch.h b/installer/PowerToysBootstrapper/bootstrapper/pch.h index 80934f7d2..d305b4191 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/pch.h +++ b/installer/PowerToysBootstrapper/bootstrapper/pch.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -22,8 +23,10 @@ #include #include +#pragma warning(push, 0) #include #include #include +#pragma warning(pop) #include diff --git a/installer/PowerToysBootstrapper/bootstrapper/progressbar_window.cpp b/installer/PowerToysBootstrapper/bootstrapper/progressbar_window.cpp index 1270da086..78ee2a541 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/progressbar_window.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/progressbar_window.cpp @@ -1,6 +1,5 @@ #include "pch.h" -#include #include #include "progressbar_window.h" diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 9a7cbf205..9cced7747 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -359,6 +359,9 @@ + + + @@ -869,6 +872,7 @@ + diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp index d7d82d212..bf0e61835 100644 --- a/installer/PowerToysSetupCustomActions/CustomAction.cpp +++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp @@ -2,6 +2,7 @@ #include +#include "../../src/common/utils/MsiUtils.h" #include "../../src/common/updating/installer.h" #include "../../src/common/version/version.h" @@ -582,7 +583,7 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall) try { - if (auto install_path = updating::get_msi_package_installed_path()) + if (auto install_path = GetMsiPackageInstalledPath()) { MsiSetPropertyW(hInstall, L"INSTALLFOLDER", install_path->data()); } diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj index dde59dc0f..226a80002 100644 --- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj +++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj @@ -56,7 +56,7 @@ $(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;..\..\$(PlatformShortName)\$(Configuration)\;%(AdditionalLibraryDirectories) - msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;winstore.lib;Shlwapi.lib;%(AdditionalDependencies) + msi.lib;wcautil.lib;Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;ApplicationUpdate.lib;Notifications.lib;Shlwapi.lib;%(AdditionalDependencies) diff --git a/src/ActionRunner/Resources.resx b/src/ActionRunner/Resources.resx index 7e2feb197..443b7b0f4 100644 --- a/src/ActionRunner/Resources.resx +++ b/src/ActionRunner/Resources.resx @@ -64,28 +64,7 @@ PowerToys installation error - - An update to PowerToys is available. - - - Update now - - - Error: please uninstall the previous version of PowerToys manually. - An update to PowerToys is available. Visit our GitHub page to update. - - More info... - - - PowerToys Update - - - We've detected a previous installation of PowerToys. Would you like to remove it? - - - PowerToys: uninstall previous version? - diff --git a/src/ActionRunner/actionRunner.cpp b/src/ActionRunner/actionRunner.cpp index bfd54f816..28381ee92 100644 --- a/src/ActionRunner/actionRunner.cpp +++ b/src/ActionRunner/actionRunner.cpp @@ -11,12 +11,6 @@ #include #include -#include -#include -#include -#include -#include - #include #include #include @@ -28,214 +22,14 @@ #include #include -#include #include "../runner/tray_icon.h" -#include "../runner/action_runner_utils.h" - -auto Strings = create_notifications_strings(); +#include "../runner/ActionRunnerUtils.h" using namespace cmdArg; -int UninstallMsiAction() -{ - const auto package_path = updating::get_msi_package_path(); - if (package_path.empty()) - { - return 0; - } - - if (!updating::uninstall_msi_version(package_path, Strings)) - { - return -1; - } - - // Launch PowerToys again, since it's been terminated by the MSI uninstaller - std::wstring runner_path{ winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path() }; - runner_path += L"\\PowerToys.exe"; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC }; - sei.lpFile = runner_path.c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteExW(&sei); - - return 0; -} - namespace fs = std::filesystem; -std::optional CopySelfToTempDir() -{ - std::error_code error; - auto dst_path = fs::temp_directory_path() / "PowerToys.ActionRunner.exe"; - fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error); - if (error) - { - return std::nullopt; - } - - return std::move(dst_path); -} - -std::optional ObtainInstallerPath() -{ - using namespace updating; - - auto state = UpdateState::read(); - if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading) - { - const auto new_version_info = get_github_version_info_async(Strings).get(); - if (!new_version_info) - { - Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error()); - return std::nullopt; - } - - if (!std::holds_alternative(*new_version_info)) - { - Logger::error("Invoked with -update_now argument, but no update was available"); - return std::nullopt; - } - - auto downloaded_installer = download_new_version(std::get(*new_version_info)).get(); - if (!downloaded_installer) - { - Logger::error("Couldn't download new installer"); - } - - return downloaded_installer; - } - else if (state.state == UpdateState::readyToInstall) - { - fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename }; - if (fs::is_regular_file(installer)) - { - return std::move(installer); - } - else - { - Logger::error(L"Couldn't find a downloaded installer {}", installer.native()); - return std::nullopt; - } - } - else - { - Logger::error("Invoked with -update_now argument, but update state was invalid"); - return std::nullopt; - } -} - -bool InstallNewVersionStage1() -{ - const auto installer = ObtainInstallerPath(); - if (!installer) - { - return false; - } - - if (auto copy_in_temp = CopySelfToTempDir()) - { - // Detect if PT was running - const auto pt_main_window = FindWindowW(pt_tray_icon_window_class, nullptr); - const bool launch_powertoys = pt_main_window != nullptr; - if (pt_main_window != nullptr) - { - SendMessageW(pt_main_window, WM_CLOSE, 0, 0); - } - - std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 }; - arguments += L" \""; - arguments += installer->c_str(); - arguments += L"\" \""; - arguments += get_module_folderpath(); - arguments += L"\" "; - arguments += launch_powertoys ? UPDATE_STAGE2_RESTART_PT : UPDATE_STAGE2_DONT_START_PT; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC }; - sei.lpFile = copy_in_temp->c_str(); - sei.nShow = SW_SHOWNORMAL; - - sei.lpParameters = arguments.c_str(); - return ShellExecuteExW(&sei) == TRUE; - } - else - { - return false; - } -} - -bool InstallNewVersionStage2(std::wstring installer_path, std::wstring_view install_path, bool launch_powertoys) -{ - std::transform(begin(installer_path), end(installer_path), begin(installer_path), ::towlower); - - bool success = true; - - if (installer_path.ends_with(L".msi")) - { - success = MsiInstallProductW(installer_path.data(), nullptr) == ERROR_SUCCESS; - } - else - { - // If it's not .msi, then it's our .exe installer - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE }; - sei.lpFile = installer_path.c_str(); - sei.nShow = SW_SHOWNORMAL; - std::wstring parameters = L"--no_full_ui"; - if (launch_powertoys) - { - // .exe installer launches the main app by default - launch_powertoys = false; - } - else - { - parameters += L"--no_start_pt"; - } - - sei.lpParameters = parameters.c_str(); - - success = ShellExecuteExW(&sei) == TRUE; - - // Wait for the install completion - if (success) - { - WaitForSingleObject(sei.hProcess, INFINITE); - DWORD exitCode = 0; - GetExitCodeProcess(sei.hProcess, &exitCode); - success = exitCode == 0; - CloseHandle(sei.hProcess); - } - } - - if (!success) - { - return false; - } - - std::error_code _; - fs::remove(installer_path, _); - - UpdateState::store([&](UpdateState& state) { - state = {}; - state.githubUpdateLastCheckedDate.emplace(timeutil::now()); - state.state = UpdateState::upToDate; - }); - - if (launch_powertoys) - { - std::wstring new_pt_path{ install_path }; - new_pt_path += L"\\PowerToys.exe"; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC }; - sei.lpFile = new_pt_path.c_str(); - sei.nShow = SW_SHOWNORMAL; - sei.lpParameters = UPDATE_REPORT_SUCCESS; - return ShellExecuteExW(&sei) == TRUE; - } - - return true; -} - int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { int nArgs = 0; @@ -312,37 +106,6 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) } } } - else if (action == UNINSTALL_MSI) - { - return UninstallMsiAction(); - } - else if (action == UPDATE_NOW_LAUNCH_STAGE1) - { - const bool failed = !InstallNewVersionStage1(); - if (failed) - { - UpdateState::store([&](UpdateState& state) { - state.downloadedInstallerFilename = {}; - state.githubUpdateLastCheckedDate.emplace(timeutil::now()); - state.state = UpdateState::errorDownloading; - }); - } - return failed; - } - else if (action == UPDATE_NOW_LAUNCH_STAGE2) - { - using namespace std::string_view_literals; - const bool failed = !InstallNewVersionStage2(args[2], args[3], args[4] == std::wstring_view{ UPDATE_STAGE2_RESTART_PT }); - if (failed) - { - UpdateState::store([&](UpdateState& state) { - state.downloadedInstallerFilename = {}; - state.githubUpdateLastCheckedDate.emplace(timeutil::now()); - state.state = UpdateState::errorDownloading; - }); - } - return failed; - } return 0; } diff --git a/src/ActionRunner/actionRunner.vcxproj b/src/ActionRunner/actionRunner.vcxproj index 126508090..04855caae 100644 --- a/src/ActionRunner/actionRunner.vcxproj +++ b/src/ActionRunner/actionRunner.vcxproj @@ -41,15 +41,9 @@ {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} - - {1d5be09d-78c0-4fd7-af00-ae7c1af7c525} - {6955446d-23f7-4023-9bb3-8657f904af99} - - {17da04df-e393-4397-9cf0-84dabe11032e} - diff --git a/src/Update/LocProject.json b/src/Update/LocProject.json new file mode 100644 index 000000000..c4ca89a4a --- /dev/null +++ b/src/Update/LocProject.json @@ -0,0 +1,14 @@ +{ + "Projects": [ + { + "LanguageSet": "Azure_Languages", + "LocItems": [ + { + "SourceFile": "src\\Update\\Resources.resx", + "CopyOption": "LangIDOnName", + "OutputPath": "src\\Update" + } + ] + } + ] +} diff --git a/src/Update/PowerToys.Update.base.rc b/src/Update/PowerToys.Update.base.rc new file mode 100644 index 000000000..5e4e3aab3 --- /dev/null +++ b/src/Update/PowerToys.Update.base.rc @@ -0,0 +1,36 @@ +#include +#include "resource.h" +#include "../common/version/version.h" + +1 VERSIONINFO +FILEVERSION FILE_VERSION +PRODUCTVERSION PRODUCT_VERSION +FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG +FILEFLAGS VS_FF_DEBUG +#else +FILEFLAGS 0x0L +#endif +FILEOS VOS_NT_WINDOWS32 +FILETYPE VFT_DLL +FILESUBTYPE VFT2_UNKNOWN +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" // US English (0x0409), Unicode (0x04B0) charset + BEGIN + VALUE "CompanyName", COMPANY_NAME + VALUE "FileDescription", FILE_DESCRIPTION + VALUE "FileVersion", FILE_VERSION_STRING + VALUE "InternalName", INTERNAL_NAME + VALUE "LegalCopyright", COPYRIGHT_NOTE + VALUE "OriginalFilename", ORIGINAL_FILENAME + VALUE "ProductName", PRODUCT_NAME + VALUE "ProductVersion", PRODUCT_VERSION_STRING + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 // US English (0x0409), Unicode (1200) charset + END +END diff --git a/src/Update/PowerToys.Update.cpp b/src/Update/PowerToys.Update.cpp new file mode 100644 index 000000000..13c7a11b5 --- /dev/null +++ b/src/Update/PowerToys.Update.cpp @@ -0,0 +1,255 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#define WIN32_LEAN_AND_MEAN +#include "Generated Files/resource.h" + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include "../runner/tray_icon.h" +#include "../runner/UpdateUtils.h" + +using namespace cmdArg; + +namespace fs = std::filesystem; + +std::optional CopySelfToTempDir() +{ + std::error_code error; + auto dst_path = fs::temp_directory_path() / "PowerToys.Update.exe"; + fs::copy_file(get_module_filename(), dst_path, fs::copy_options::overwrite_existing, error); + if (error) + { + return std::nullopt; + } + + return std::move(dst_path); +} + +std::optional ObtainInstallerPath() +{ + using namespace updating; + + auto state = UpdateState::read(); + if (state.state == UpdateState::readyToDownload || state.state == UpdateState::errorDownloading) + { + const auto new_version_info = get_github_version_info_async().get(); + if (!new_version_info) + { + Logger::error(L"Couldn't obtain github version info: {}", new_version_info.error()); + return std::nullopt; + } + + if (!std::holds_alternative(*new_version_info)) + { + Logger::error("Invoked with -update_now argument, but no update was available"); + return std::nullopt; + } + + auto downloaded_installer = download_new_version(std::get(*new_version_info)).get(); + if (!downloaded_installer) + { + Logger::error("Couldn't download new installer"); + } + + return downloaded_installer; + } + else if (state.state == UpdateState::readyToInstall) + { + fs::path installer{ get_pending_updates_path() / state.downloadedInstallerFilename }; + if (fs::is_regular_file(installer)) + { + return std::move(installer); + } + else + { + Logger::error(L"Couldn't find a downloaded installer {}", installer.native()); + return std::nullopt; + } + } + else + { + Logger::error("Invoked with -update_now argument, but update state was invalid"); + return std::nullopt; + } +} + +bool InstallNewVersionStage1() +{ + const auto installer = ObtainInstallerPath(); + if (!installer) + { + return false; + } + + if (auto copy_in_temp = CopySelfToTempDir()) + { + // Detect if PT was running + const auto pt_main_window = FindWindowW(pt_tray_icon_window_class, nullptr); + const bool launch_powertoys = pt_main_window != nullptr; + if (pt_main_window != nullptr) + { + SendMessageW(pt_main_window, WM_CLOSE, 0, 0); + } + + std::wstring arguments{ UPDATE_NOW_LAUNCH_STAGE2 }; + arguments += L" \""; + arguments += installer->c_str(); + arguments += L"\" \""; + arguments += get_module_folderpath(); + arguments += L"\" "; + arguments += launch_powertoys ? UPDATE_STAGE2_RESTART_PT : UPDATE_STAGE2_DONT_START_PT; + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC }; + sei.lpFile = copy_in_temp->c_str(); + sei.nShow = SW_SHOWNORMAL; + + sei.lpParameters = arguments.c_str(); + return ShellExecuteExW(&sei) == TRUE; + } + else + { + return false; + } +} + +bool InstallNewVersionStage2(std::wstring installer_path, std::wstring_view install_path, bool launch_powertoys) +{ + std::transform(begin(installer_path), end(installer_path), begin(installer_path), ::towlower); + + bool success = true; + + if (installer_path.ends_with(L".msi")) + { + success = MsiInstallProductW(installer_path.data(), nullptr) == ERROR_SUCCESS; + } + else + { + // If it's not .msi, then it's our .exe installer + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE }; + sei.lpFile = installer_path.c_str(); + sei.nShow = SW_SHOWNORMAL; + std::wstring parameters = L"--no_full_ui"; + if (launch_powertoys) + { + // .exe installer launches the main app by default + launch_powertoys = false; + } + else + { + parameters += L"--no_start_pt"; + } + + sei.lpParameters = parameters.c_str(); + + success = ShellExecuteExW(&sei) == TRUE; + + // Wait for the install completion + if (success) + { + WaitForSingleObject(sei.hProcess, INFINITE); + DWORD exitCode = 0; + GetExitCodeProcess(sei.hProcess, &exitCode); + success = exitCode == 0; + CloseHandle(sei.hProcess); + } + } + + if (!success) + { + return false; + } + + std::error_code _; + fs::remove(installer_path, _); + + UpdateState::store([&](UpdateState& state) { + state = {}; + state.githubUpdateLastCheckedDate.emplace(timeutil::now()); + state.state = UpdateState::upToDate; + }); + + if (launch_powertoys) + { + std::wstring new_pt_path{ install_path }; + new_pt_path += L"\\PowerToys.exe"; + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC }; + sei.lpFile = new_pt_path.c_str(); + sei.nShow = SW_SHOWNORMAL; + sei.lpParameters = UPDATE_REPORT_SUCCESS; + return ShellExecuteExW(&sei) == TRUE; + } + + return true; +} + +int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) +{ + int nArgs = 0; + LPWSTR* args = CommandLineToArgvW(GetCommandLineW(), &nArgs); + if (!args || nArgs < 2) + { + return 1; + } + + std::wstring_view action{ args[1] }; + + std::filesystem::path logFilePath(PTSettingsHelper::get_root_save_folder_location()); + logFilePath.append(LogSettings::updateLogPath); + Logger::init(LogSettings::updateLoggerName, logFilePath.wstring(), PTSettingsHelper::get_log_settings_file_location()); + + if (action == UPDATE_NOW_LAUNCH_STAGE1) + { + const bool failed = !InstallNewVersionStage1(); + if (failed) + { + UpdateState::store([&](UpdateState& state) { + state.downloadedInstallerFilename = {}; + state.githubUpdateLastCheckedDate.emplace(timeutil::now()); + state.state = UpdateState::errorDownloading; + }); + } + return failed; + } + else if (action == UPDATE_NOW_LAUNCH_STAGE2) + { + using namespace std::string_view_literals; + const bool failed = !InstallNewVersionStage2(args[2], args[3], args[4] == std::wstring_view{ UPDATE_STAGE2_RESTART_PT }); + if (failed) + { + UpdateState::store([&](UpdateState& state) { + state.downloadedInstallerFilename = {}; + state.githubUpdateLastCheckedDate.emplace(timeutil::now()); + state.state = UpdateState::errorDownloading; + }); + } + return failed; + } + + return 0; +} diff --git a/src/Update/PowerToys.Update.vcxproj b/src/Update/PowerToys.Update.vcxproj new file mode 100644 index 000000000..76d0f4464 --- /dev/null +++ b/src/Update/PowerToys.Update.vcxproj @@ -0,0 +1,76 @@ + + + + + + + + 16.0 + {44CE9AE1-4390-42C5-BACC-0FD6B40AA203} + Update + PowerToys.Update + + + + + Application + + + + + + + + + + + + + Level4 + NotUsing + ../;%(AdditionalIncludeDirectories) + + + WindowsApp.lib;Msi.lib;Shlwapi.lib;%(AdditionalDependencies) + + + + + + + + {d9b8fc84-322a-4f9f-bbb9-20915c47ddfd} + + + {1d5be09d-78c0-4fd7-af00-ae7c1af7c525} + + + {6955446d-23f7-4023-9bb3-8657f904af99} + + + {17da04df-e393-4397-9cf0-84dabe11032e} + + + + + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/src/Update/Resources.resx b/src/Update/Resources.resx new file mode 100644 index 000000000..a141dacd3 --- /dev/null +++ b/src/Update/Resources.resx @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Couldn't download .NET Core Desktop Runtime 3.1, please install it manually. + + + PowerToys installation error + + + An update to PowerToys is available. + + + Update now + + + An update to PowerToys is available. Visit our GitHub page to update. + + + More info... + + + PowerToys Update + + diff --git a/src/common/WinStore/packages.config b/src/Update/packages.config similarity index 100% rename from src/common/WinStore/packages.config rename to src/Update/packages.config diff --git a/src/Update/resource.base.h b/src/Update/resource.base.h new file mode 100644 index 000000000..eaef55651 --- /dev/null +++ b/src/Update/resource.base.h @@ -0,0 +1,11 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by PowerToys.Update.rc + +////////////////////////////// +// Non-localizable + +#define FILE_DESCRIPTION "PowerToys Update" +#define INTERNAL_NAME "PowerToys.Update" +#define ORIGINAL_FILENAME "PowerToys.Update.exe" + diff --git a/src/common/WinStore/Winstore.vcxproj b/src/common/WinStore/Winstore.vcxproj deleted file mode 100644 index bbefd414e..000000000 --- a/src/common/WinStore/Winstore.vcxproj +++ /dev/null @@ -1,54 +0,0 @@ - - - - - 16.0 - {C502A854-53AC-4EBB-8DC0-E4AF2191E4F6} - Win32Proj - WinStore - WinStore - - - - StaticLibrary - - - - - - - - - - - - - - - - ..\..\..\;%(AdditionalIncludeDirectories) - _LIB;%(PreprocessorDefinitions) - NotUsing - - - - - - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/src/common/WinStore/winstore.cpp b/src/common/WinStore/winstore.cpp deleted file mode 100644 index 270bd61d4..000000000 --- a/src/common/WinStore/winstore.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include "winstore.h" - -#include -#include - -using winrt::Windows::ApplicationModel::StartupTask; - -namespace -{ - const wchar_t* STARTUP_TASKID = L"PowerToysStartupTaskID"; -} - -namespace winstore -{ - bool running_as_packaged() - { - UINT32 length = 0; - const auto rc = GetPackageFamilyName(GetCurrentProcess(), &length, nullptr); - return rc != APPMODEL_ERROR_NO_PACKAGE; - } - - std::future get_startup_task_status_async() - { - const auto startupTask = co_await StartupTask::GetAsync(STARTUP_TASKID); - co_return startupTask.State(); - } - - std::future switch_startup_task_state_async(const bool enabled) - { - const auto startupTask = co_await StartupTask::GetAsync(STARTUP_TASKID); - enum class action - { - none, - enable, - disable, - } action_to_try = action::none; - switch (startupTask.State()) - { - case StartupTaskState::Disabled: - if (enabled) - { - action_to_try = action::enable; - } - break; - case StartupTaskState::Enabled: - if (!enabled) - { - action_to_try = action::disable; - } - break; - } - try - { - switch (action_to_try) - { - case action::enable: - co_await startupTask.RequestEnableAsync(); - break; - case action::disable: - startupTask.Disable(); - break; - } - } - catch (...) - { - // We can't handle the error, in case we don't have a permission to change startup task state - } - } - -} diff --git a/src/common/WinStore/winstore.h b/src/common/WinStore/winstore.h deleted file mode 100644 index 514bfeef0..000000000 --- a/src/common/WinStore/winstore.h +++ /dev/null @@ -1,16 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -namespace winstore -{ - using winrt::Windows::ApplicationModel::StartupTaskState; - - bool running_as_packaged(); - std::future switch_startup_task_state_async(const bool enabled); - std::future get_startup_task_status_async(); -} diff --git a/src/common/logger/logger_settings.h b/src/common/logger/logger_settings.h index 995c50ee8..d4ea19a40 100644 --- a/src/common/logger/logger_settings.h +++ b/src/common/logger/logger_settings.h @@ -11,6 +11,8 @@ struct LogSettings inline const static std::wstring runnerLogPath = L"RunnerLogs\\runner-log.txt"; inline const static std::string actionRunnerLoggerName = "action-runner"; inline const static std::wstring actionRunnerLogPath = L"RunnerLogs\\action-runner-log.txt"; + inline const static std::string updateLoggerName = "update"; + inline const static std::wstring updateLogPath = L"UpdateLogs\\update-log.txt"; inline const static std::string launcherLoggerName = "launcher"; inline const static std::wstring launcherLogPath = L"LogsModuleInterface\\launcher-log.txt"; inline const static std::wstring awakeLogPath = L"Logs\\awake-log.txt"; diff --git a/src/common/notifications/notifications.cpp b/src/common/notifications/notifications.cpp index ed10ec4eb..4d58bcbb3 100644 --- a/src/common/notifications/notifications.cpp +++ b/src/common/notifications/notifications.cpp @@ -3,7 +3,6 @@ #include "notifications.h" #include "utils/com_object_factory.h" #include "utils/window.h" -#include "winstore/winstore.h" #include #include @@ -201,41 +200,6 @@ void notifications::override_application_id(const std::wstring_view appID) SetCurrentProcessExplicitAppUserModelID(APPLICATION_ID.c_str()); } -void notifications::register_background_toast_handler() -{ - if (!winstore::running_as_packaged()) - { - // The WIX installer will have us registered via the registry - return; - } - try - { - // Re-request access to clean up from previous PowerToys installations - BackgroundExecutionManager::RemoveAccess(); - BackgroundExecutionManager::RequestAccessAsync().get(); - - BackgroundTaskBuilder builder; - ToastNotificationActionTrigger trigger{ PACKAGED_APPLICATION_ID }; - builder.SetTrigger(trigger); - builder.TaskEntryPoint(TASK_ENTRYPOINT); - builder.Name(TASK_NAME); - - const auto tasks = BackgroundTaskRegistration::AllTasks(); - const bool already_registered = std::any_of(begin(tasks), end(tasks), [=](const auto& task) { - return task.Value().Name() == TASK_NAME; - }); - if (already_registered) - { - return; - } - (void)builder.Register(); - } - catch (...) - { - // Couldn't register the background task, nothing we can do - } -} - void notifications::show_toast(std::wstring message, std::wstring title, toast_params params) { // The toast won't be actually activated in the background, since it doesn't have any buttons @@ -402,8 +366,8 @@ void notifications::show_toast_with_activations(std::wstring message, NotificationData data{ map }; notification.Data(std::move(data)); - const auto notifier = winstore::running_as_packaged() ? ToastNotificationManager::ToastNotificationManager::CreateToastNotifier() : - ToastNotificationManager::ToastNotificationManager::CreateToastNotifier(APPLICATION_ID); + const auto notifier = + ToastNotificationManager::ToastNotificationManager::CreateToastNotifier(APPLICATION_ID); // Set a tag-related params if it has a valid length if (params.tag.has_value() && params.tag->length() < 64) @@ -431,9 +395,8 @@ void notifications::show_toast_with_activations(std::wstring message, void notifications::update_toast_progress_bar(std::wstring_view tag, progress_bar_params params) { - const auto notifier = winstore::running_as_packaged() ? - ToastNotificationManager::ToastNotificationManager::CreateToastNotifier() : - ToastNotificationManager::ToastNotificationManager::CreateToastNotifier(APPLICATION_ID); + const auto notifier = + ToastNotificationManager::ToastNotificationManager::CreateToastNotifier(APPLICATION_ID); float progress = std::clamp(params.progress, 0.0f, 1.0f); winrt::Windows::Foundation::Collections::StringMap map; @@ -468,8 +431,7 @@ void notifications::remove_toasts_by_tag(std::wstring_view tag) void notifications::remove_all_scheduled_toasts() { - const auto notifier = winstore::running_as_packaged() ? ToastNotificationManager::ToastNotificationManager::CreateToastNotifier() : - ToastNotificationManager::ToastNotificationManager::CreateToastNotifier(APPLICATION_ID); + const auto notifier = ToastNotificationManager::ToastNotificationManager::CreateToastNotifier(APPLICATION_ID); try { diff --git a/src/common/notifications/notifications.h b/src/common/notifications/notifications.h index 4e4ea6fd9..4f4247f15 100644 --- a/src/common/notifications/notifications.h +++ b/src/common/notifications/notifications.h @@ -12,7 +12,6 @@ namespace notifications constexpr inline const wchar_t UPDATING_PROCESS_TOAST_TAG[] = L"PTUpdateNotifyTag"; void override_application_id(const std::wstring_view appID); - void register_background_toast_handler(); void run_desktop_app_activator_loop(); bool register_application_id(const std::wstring_view appName, const std::wstring_view iconPath); diff --git a/src/common/notifications/notifications.vcxproj b/src/common/notifications/notifications.vcxproj index 2d2e4d652..b76d42a3b 100644 --- a/src/common/notifications/notifications.vcxproj +++ b/src/common/notifications/notifications.vcxproj @@ -39,11 +39,6 @@ - - - {c502a854-53ac-4ebb-8dc0-e4af2191e4f6} - - diff --git a/src/common/updating/http_client.cpp b/src/common/updating/http_client.cpp deleted file mode 100644 index 951d841d8..000000000 --- a/src/common/updating/http_client.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "pch.h" -#include "http_client.h" - -#include -#include -#include - -namespace http -{ - using namespace winrt::Windows::Web::Http; - namespace storage = winrt::Windows::Storage; - - const wchar_t USER_AGENT[] = L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"; - - HttpClient::HttpClient() - { - auto headers = m_client.DefaultRequestHeaders(); - headers.UserAgent().TryParseAdd(USER_AGENT); - } - - std::future HttpClient::request(const winrt::Windows::Foundation::Uri& url) - { - auto response = co_await m_client.GetAsync(url); - (void)response.EnsureSuccessStatusCode(); - auto body = co_await response.Content().ReadAsStringAsync(); - co_return std::wstring(body); - } - - std::future HttpClient::download(const winrt::Windows::Foundation::Uri& url, const std::wstring& dstFilePath) - { - auto response = co_await m_client.GetAsync(url); - (void)response.EnsureSuccessStatusCode(); - auto file_stream = co_await storage::Streams::FileRandomAccessStream::OpenAsync(dstFilePath.c_str(), storage::FileAccessMode::ReadWrite, storage::StorageOpenOptions::AllowReadersAndWriters, storage::Streams::FileOpenDisposition::CreateAlways); - co_await response.Content().WriteToStreamAsync(file_stream); - file_stream.Close(); - } - - std::future HttpClient::download(const winrt::Windows::Foundation::Uri& url, const std::wstring& dstFilePath, const std::function& progressUpdateCallback) - { - auto response = co_await m_client.GetAsync(url, HttpCompletionOption::ResponseHeadersRead); - response.EnsureSuccessStatusCode(); - - uint64_t totalBytes = response.Content().Headers().ContentLength().GetUInt64(); - auto contentStream = co_await response.Content().ReadAsInputStreamAsync(); - - uint64_t totalBytesRead = 0; - storage::Streams::Buffer buffer(8192); - auto fileStream = co_await storage::Streams::FileRandomAccessStream::OpenAsync(dstFilePath.c_str(), storage::FileAccessMode::ReadWrite, storage::StorageOpenOptions::AllowReadersAndWriters, storage::Streams::FileOpenDisposition::CreateAlways); - - co_await contentStream.ReadAsync(buffer, buffer.Capacity(), storage::Streams::InputStreamOptions::None); - while (buffer.Length() > 0) - { - co_await fileStream.WriteAsync(buffer); - totalBytesRead += buffer.Length(); - if (progressUpdateCallback) - { - float percentage = (float)totalBytesRead / totalBytes; - progressUpdateCallback(percentage); - } - - co_await contentStream.ReadAsync(buffer, buffer.Capacity(), storage::Streams::InputStreamOptions::None); - } - - if (progressUpdateCallback) - { - progressUpdateCallback(1); - } - - fileStream.Close(); - contentStream.Close(); - } -} \ No newline at end of file diff --git a/src/common/updating/http_client.h b/src/common/updating/http_client.h deleted file mode 100644 index 396c61271..000000000 --- a/src/common/updating/http_client.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include -#include - -namespace http -{ - class HttpClient - { - public: - HttpClient(); - std::future request(const winrt::Windows::Foundation::Uri& url); - std::future download(const winrt::Windows::Foundation::Uri& url, const std::wstring& dstFle); - std::future download(const winrt::Windows::Foundation::Uri& url, const std::wstring& dstFle, const std::function& progressUpdateCallback); - - private: - winrt::Windows::Web::Http::HttpClient m_client; - }; -} diff --git a/src/common/updating/installer.cpp b/src/common/updating/installer.cpp index 91572d0dd..2be4a97c5 100644 --- a/src/common/updating/installer.cpp +++ b/src/common/updating/installer.cpp @@ -2,171 +2,22 @@ #include "installer.h" #include -#include +#include #include #include "utils/winapi_error.h" namespace // Strings in this namespace should not be localized { - const wchar_t POWER_TOYS_UPGRADE_CODE[] = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}"; - const wchar_t DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH[] = L"delete_previous_powertoys_confirm"; const wchar_t TOAST_TITLE[] = L"PowerToys"; const wchar_t MSIX_PACKAGE_NAME[] = L"Microsoft.PowerToys"; const wchar_t MSIX_PACKAGE_PUBLISHER[] = L"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"; - - const wchar_t POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; } namespace updating { - std::wstring get_msi_package_path() - { - std::wstring package_path; - wchar_t GUID_product_string[39]; - if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, GUID_product_string); !found) - { - return package_path; - } - - if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(GUID_product_string); !installed) - { - return package_path; - } - - DWORD package_path_size = 0; - - if (const bool has_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size); !has_package_path) - { - return package_path; - } - - package_path = std::wstring(++package_path_size, L'\0'); - if (const bool got_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size); !got_package_path) - { - package_path = {}; - return package_path; - } - - package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW - - return package_path; - } - - bool offer_msi_uninstallation(const notifications::strings& strings) - { - const auto selection = SHMessageBoxCheckW(nullptr, - strings.OFFER_UNINSTALL_MSI.c_str(), - strings.OFFER_UNINSTALL_MSI_TITLE.c_str(), - MB_ICONQUESTION | MB_YESNO, - IDNO, - DONT_SHOW_AGAIN_RECORD_REGISTRY_PATH); - return selection == IDYES; - } - - bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings& strings) - { - const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); - if (ERROR_SUCCESS == uninstall_result) - { - return true; - } - else if (auto system_message = get_last_error_message(uninstall_result); system_message.has_value()) - { - try - { - ::notifications::show_toast(*system_message, TOAST_TITLE); - } - catch (...) - { - MessageBoxW(nullptr, strings.UNINSTALLATION_UNKNOWN_ERROR.c_str(), strings.NOTIFICATION_TITLE.c_str(), MB_OK | MB_ICONERROR); - } - } - return false; - } - - std::optional get_msi_package_installed_path() - { - 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) - { - return std::nullopt; - } - - if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(product_ID); !installed) - { - return std::nullopt; - } - - DWORD buf_size = MAX_PATH; - wchar_t buf[MAX_PATH]; - if (ERROR_SUCCESS == MsiGetProductInfoW(product_ID, INSTALLPROPERTY_INSTALLLOCATION, buf, &buf_size) && buf_size) - { - return buf; - } - - DWORD package_path_size = 0; - - if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size)) - { - return std::nullopt; - } - std::wstring package_path(++package_path_size, L'\0'); - - if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size)) - { - return std::nullopt; - } - package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW - - wchar_t path[MAX_PATH]; - DWORD path_size = MAX_PATH; - MsiGetComponentPathW(product_ID, POWERTOYS_EXE_COMPONENT, path, &path_size); - if (!path_size) - { - return std::nullopt; - } - PathCchRemoveFileSpec(path, path_size); - return path; - } - - std::optional get_installed_powertoys_version() - { - auto installed_path = get_msi_package_installed_path(); - if (!installed_path) - { - return std::nullopt; - } - *installed_path += L"\\PowerToys.exe"; - - // Get the version information for the file requested - const DWORD fvSize = GetFileVersionInfoSizeW(installed_path->c_str(), nullptr); - if (!fvSize) - { - return std::nullopt; - } - - auto pbVersionInfo = std::make_unique(fvSize); - - if (!GetFileVersionInfoW(installed_path->c_str(), 0, fvSize, pbVersionInfo.get())) - { - return std::nullopt; - } - - VS_FIXEDFILEINFO* fileInfo = nullptr; - UINT fileInfoLen = 0; - if (!VerQueryValueW(pbVersionInfo.get(), L"\\", reinterpret_cast(&fileInfo), &fileInfoLen)) - { - return std::nullopt; - } - return VersionHelper{ (fileInfo->dwFileVersionMS >> 16) & 0xffff, - (fileInfo->dwFileVersionMS >> 0) & 0xffff, - (fileInfo->dwFileVersionLS >> 16) & 0xffff }; - } - std::future uninstall_previous_msix_version_async() { winrt::Windows::Management::Deployment::PackageManager package_manager; @@ -192,9 +43,4 @@ namespace updating } co_return false; } - - bool is_1809_or_older() - { - return !Is19H1OrHigher(); - } } \ No newline at end of file diff --git a/src/common/updating/installer.h b/src/common/updating/installer.h index 0da895248..5f2ca4bbb 100644 --- a/src/common/updating/installer.h +++ b/src/common/updating/installer.h @@ -4,18 +4,9 @@ #include #include -#include "notifications.h" #include namespace updating { - std::wstring get_msi_package_path(); - bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings&); - bool offer_msi_uninstallation(const notifications::strings&); - std::optional get_msi_package_installed_path(); - - std::optional get_installed_powertoys_version(); std::future uninstall_previous_msix_version_async(); - - bool is_1809_or_older(); } \ No newline at end of file diff --git a/src/common/updating/notifications.cpp b/src/common/updating/notifications.cpp deleted file mode 100644 index 7a08a1031..000000000 --- a/src/common/updating/notifications.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "pch.h" - -#include "notifications.h" - -#include - -#include "updating.h" - -#include -#include - -namespace updating -{ - namespace notifications - { - using namespace ::notifications; - std::wstring current_version_to_next_version(const new_version_download_info& info) - { - auto current_version_to_next_version = VersionHelper{ VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION }.toWstring(); - current_version_to_next_version += L" -> "; - current_version_to_next_version += info.version.toWstring(); - return current_version_to_next_version; - } - - void show_new_version_available(const new_version_download_info& info, const strings& strings) - { - remove_toasts_by_tag(UPDATING_PROCESS_TOAST_TAG); - - toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; - std::wstring contents = strings.GITHUB_NEW_VERSION_AVAILABLE; - contents += L'\n'; - contents += current_version_to_next_version(info); - - show_toast_with_activations(std::move(contents), - strings.NOTIFICATION_TITLE, - {}, - { link_button{ strings.GITHUB_NEW_VERSION_UPDATE_NOW, - L"powertoys://update_now/" }, - link_button{ strings.GITHUB_NEW_VERSION_MORE_INFO, - L"powertoys://open_settings/" } }, - std::move(toast_params)); - } - - void show_open_settings_for_update(const strings& strings) - { - remove_toasts_by_tag(UPDATING_PROCESS_TOAST_TAG); - - toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; - - std::vector actions = { - link_button{ strings.GITHUB_NEW_VERSION_MORE_INFO, - L"powertoys://open_settings/" }, - }; - show_toast_with_activations(strings.GITHUB_NEW_VERSION_AVAILABLE, - strings.NOTIFICATION_TITLE, - {}, - std::move(actions), - std::move(toast_params)); - } - } -} diff --git a/src/common/updating/notifications.h b/src/common/updating/notifications.h deleted file mode 100644 index 421a32d71..000000000 --- a/src/common/updating/notifications.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include - -namespace updating -{ - struct new_version_download_info; - - namespace notifications - { - struct strings - { - std::wstring GITHUB_NEW_VERSION_AVAILABLE; - std::wstring GITHUB_NEW_VERSION_MORE_INFO; - std::wstring GITHUB_NEW_VERSION_UPDATE_NOW; - - std::wstring OFFER_UNINSTALL_MSI; - std::wstring OFFER_UNINSTALL_MSI_TITLE; - - std::wstring NOTIFICATION_TITLE; - - std::wstring UNINSTALLATION_UNKNOWN_ERROR; - }; - - void show_new_version_available(const new_version_download_info& info, const strings& strings); - void show_open_settings_for_update(const strings& strings); - } -} - -#define create_notifications_strings() \ - ::updating::notifications::strings \ - { \ - .GITHUB_NEW_VERSION_AVAILABLE = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_AVAILABLE), \ - .GITHUB_NEW_VERSION_MORE_INFO = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_MORE_INFO), \ - .GITHUB_NEW_VERSION_UPDATE_NOW = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UPDATE_NOW), \ - .OFFER_UNINSTALL_MSI = GET_RESOURCE_STRING(IDS_OFFER_UNINSTALL_MSI), \ - .OFFER_UNINSTALL_MSI_TITLE = GET_RESOURCE_STRING(IDS_OFFER_UNINSTALL_MSI_TITLE), \ - .NOTIFICATION_TITLE = GET_RESOURCE_STRING(IDS_TOAST_TITLE), \ - .UNINSTALLATION_UNKNOWN_ERROR = GET_RESOURCE_STRING(IDS_UNINSTALLATION_UNKNOWN_ERROR) \ - } diff --git a/src/common/updating/updating.cpp b/src/common/updating/updating.cpp index a80017ed4..35883b8f7 100644 --- a/src/common/updating/updating.cpp +++ b/src/common/updating/updating.cpp @@ -1,13 +1,11 @@ #include "pch.h" +#include #include #include -#include "http_client.h" -#include "notifications.h" #include "updating.h" -#include #include #include @@ -76,7 +74,7 @@ namespace updating throw std::runtime_error("Release object doesn't have the required asset"); } - std::future> get_github_version_info_async(const notifications::strings& strings, const bool prerelease) + std::future> get_github_version_info_async(const bool prerelease) { // If the current version starts with 0.0.*, it means we're on a local build from a farm and shouldn't check for updates. if (VERSION_MAJOR == 0 && VERSION_MINOR == 0) diff --git a/src/common/updating/updating.h b/src/common/updating/updating.h index 1aac92d71..a5a15e47d 100644 --- a/src/common/updating/updating.h +++ b/src/common/updating/updating.h @@ -8,7 +8,6 @@ #include #include -#include "notifications.h" #include namespace updating @@ -28,7 +27,7 @@ namespace updating std::future> download_new_version(const new_version_download_info& new_version); std::filesystem::path get_pending_updates_path(); - std::future> get_github_version_info_async(const notifications::strings& strings, const bool prerelease = false); + std::future> get_github_version_info_async(const bool prerelease = false); // non-localized constexpr inline std::wstring_view INSTALLER_FILENAME_PATTERN = L"powertoyssetup"; diff --git a/src/common/updating/updating.vcxproj b/src/common/updating/updating.vcxproj index c9caaba5c..7d060e588 100644 --- a/src/common/updating/updating.vcxproj +++ b/src/common/updating/updating.vcxproj @@ -35,20 +35,13 @@ - - - - - - - @@ -56,9 +49,6 @@ - - {1d5be09d-78c0-4fd7-af00-ae7c1af7c525} - {6955446d-23f7-4023-9bb3-8657f904af99} diff --git a/src/common/updating/updating.vcxproj.filters b/src/common/updating/updating.vcxproj.filters index 640764edd..d6e5b80e0 100644 --- a/src/common/updating/updating.vcxproj.filters +++ b/src/common/updating/updating.vcxproj.filters @@ -21,21 +21,15 @@ Header Files - - Header Files - - - Header Files - - - Header Files - Header Files Header Files + + Header Files + @@ -44,18 +38,12 @@ Source Files - - Source Files - - - Source Files - - - Source Files - Source Files + + Source Files + diff --git a/src/common/utils/HttpClient.h b/src/common/utils/HttpClient.h new file mode 100644 index 000000000..86b201a5d --- /dev/null +++ b/src/common/utils/HttpClient.h @@ -0,0 +1,79 @@ +#pragma once + +#include +#include +#include +#include +#include +namespace http +{ + using namespace winrt::Windows::Web::Http; + namespace storage = winrt::Windows::Storage; + + const inline wchar_t USER_AGENT[] = L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"; + + class HttpClient + { + public: + HttpClient() + { + auto headers = m_client.DefaultRequestHeaders(); + headers.UserAgent().TryParseAdd(USER_AGENT); + } + + std::future request(const winrt::Windows::Foundation::Uri& url) + { + auto response = co_await m_client.GetAsync(url); + (void)response.EnsureSuccessStatusCode(); + auto body = co_await response.Content().ReadAsStringAsync(); + co_return std::wstring(body); + } + + std::future download(const winrt::Windows::Foundation::Uri& url, const std::wstring& dstFilePath) + { + auto response = co_await m_client.GetAsync(url); + (void)response.EnsureSuccessStatusCode(); + auto file_stream = co_await storage::Streams::FileRandomAccessStream::OpenAsync(dstFilePath.c_str(), storage::FileAccessMode::ReadWrite, storage::StorageOpenOptions::AllowReadersAndWriters, storage::Streams::FileOpenDisposition::CreateAlways); + co_await response.Content().WriteToStreamAsync(file_stream); + file_stream.Close(); + } + + std::future download(const winrt::Windows::Foundation::Uri& url, const std::wstring& dstFilePath, const std::function& progressUpdateCallback) + { + auto response = co_await m_client.GetAsync(url, HttpCompletionOption::ResponseHeadersRead); + response.EnsureSuccessStatusCode(); + + uint64_t totalBytes = response.Content().Headers().ContentLength().GetUInt64(); + auto contentStream = co_await response.Content().ReadAsInputStreamAsync(); + + uint64_t totalBytesRead = 0; + storage::Streams::Buffer buffer(8192); + auto fileStream = co_await storage::Streams::FileRandomAccessStream::OpenAsync(dstFilePath.c_str(), storage::FileAccessMode::ReadWrite, storage::StorageOpenOptions::AllowReadersAndWriters, storage::Streams::FileOpenDisposition::CreateAlways); + + co_await contentStream.ReadAsync(buffer, buffer.Capacity(), storage::Streams::InputStreamOptions::None); + while (buffer.Length() > 0) + { + co_await fileStream.WriteAsync(buffer); + totalBytesRead += buffer.Length(); + if (progressUpdateCallback) + { + float percentage = (float)totalBytesRead / totalBytes; + progressUpdateCallback(percentage); + } + + co_await contentStream.ReadAsync(buffer, buffer.Capacity(), storage::Streams::InputStreamOptions::None); + } + + if (progressUpdateCallback) + { + progressUpdateCallback(1); + } + + fileStream.Close(); + contentStream.Close(); + } + + private: + winrt::Windows::Web::Http::HttpClient m_client; + }; +} diff --git a/src/common/utils/MsiUtils.h b/src/common/utils/MsiUtils.h new file mode 100644 index 000000000..148968500 --- /dev/null +++ b/src/common/utils/MsiUtils.h @@ -0,0 +1,95 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include +#include + +#include +#include + +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 POWERTOYS_EXE_COMPONENT[] = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}"; +} + +std::optional GetMsiPackageInstalledPath() +{ + 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) + { + return std::nullopt; + } + + if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(product_ID); !installed) + { + return std::nullopt; + } + + DWORD buf_size = MAX_PATH; + wchar_t buf[MAX_PATH]; + if (ERROR_SUCCESS == MsiGetProductInfoW(product_ID, INSTALLPROPERTY_INSTALLLOCATION, buf, &buf_size) && buf_size) + { + return buf; + } + + DWORD package_path_size = 0; + + if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size)) + { + return std::nullopt; + } + std::wstring package_path(++package_path_size, L'\0'); + + if (ERROR_SUCCESS != MsiGetProductInfoW(product_ID, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size)) + { + return std::nullopt; + } + package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW + + wchar_t path[MAX_PATH]; + DWORD path_size = MAX_PATH; + MsiGetComponentPathW(product_ID, POWERTOYS_EXE_COMPONENT, path, &path_size); + if (!path_size) + { + return std::nullopt; + } + PathCchRemoveFileSpec(path, path_size); + return path; +} + +std::wstring GetMsiPackagePath() +{ + std::wstring package_path; + wchar_t GUID_product_string[39]; + if (const bool found = ERROR_SUCCESS == MsiEnumRelatedProductsW(POWER_TOYS_UPGRADE_CODE, 0, 0, GUID_product_string); !found) + { + return package_path; + } + + if (const bool installed = INSTALLSTATE_DEFAULT == MsiQueryProductStateW(GUID_product_string); !installed) + { + return package_path; + } + + DWORD package_path_size = 0; + + if (const bool has_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, nullptr, &package_path_size); !has_package_path) + { + return package_path; + } + + package_path = std::wstring(++package_path_size, L'\0'); + if (const bool got_package_path = ERROR_SUCCESS == MsiGetProductInfoW(GUID_product_string, INSTALLPROPERTY_LOCALPACKAGE, package_path.data(), &package_path_size); !got_package_path) + { + package_path = {}; + return package_path; + } + + package_path.resize(size(package_path) - 1); // trim additional \0 which we got from MsiGetProductInfoW + + return package_path; +} diff --git a/src/common/utils/elevation.h b/src/common/utils/elevation.h index 39710c1a9..0fef3dc84 100644 --- a/src/common/utils/elevation.h +++ b/src/common/utils/elevation.h @@ -5,6 +5,9 @@ #include #include +#include +#include + #include #include #include diff --git a/src/runner/ActionRunnerUtils.h b/src/runner/ActionRunnerUtils.h new file mode 100644 index 000000000..a0c59761c --- /dev/null +++ b/src/runner/ActionRunnerUtils.h @@ -0,0 +1,9 @@ +#pragma once + +#define WIN32_LEAN_AND_MEAN +#include + +namespace cmdArg +{ + const inline wchar_t* RUN_NONELEVATED = L"-run-non-elevated"; +} diff --git a/src/runner/Resources.resx b/src/runner/Resources.resx index 801a308b3..8656bfff1 100644 --- a/src/runner/Resources.resx +++ b/src/runner/Resources.resx @@ -97,9 +97,6 @@ Update now - - Error: please uninstall the previous version of PowerToys manually. - An update to PowerToys is available. Visit our GitHub page to update. @@ -109,12 +106,6 @@ PowerToys Update - - We've detected a previous installation of PowerToys. Would you like to remove it? - - - PowerToys: uninstall previous version? - Settings diff --git a/src/runner/update_utils.cpp b/src/runner/UpdateUtils.cpp similarity index 56% rename from src/runner/update_utils.cpp rename to src/runner/UpdateUtils.cpp index 4c49592dd..2231ef5ce 100644 --- a/src/runner/update_utils.cpp +++ b/src/runner/UpdateUtils.cpp @@ -2,63 +2,101 @@ #include "Generated Files/resource.h" -#include "action_runner_utils.h" +#include "ActionRunnerUtils.h" #include "general_settings.h" -#include "update_utils.h" +#include "UpdateUtils.h" #include +#include #include -#include #include #include +#include +#include #include #include - -auto Strings = create_notifications_strings(); +#include namespace { constexpr int64_t UPDATE_CHECK_INTERVAL_MINUTES = 60 * 24; constexpr int64_t UPDATE_CHECK_AFTER_FAILED_INTERVAL_MINUTES = 60 * 2; } +using namespace notifications; +using namespace updating; -bool start_msi_uninstallation_sequence() +std::wstring CurrentVersionToNextVersion(const new_version_download_info& info) { - const auto package_path = updating::get_msi_package_path(); + auto result = VersionHelper{ VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION }.toWstring(); + result += L" -> "; + result += info.version.toWstring(); + return result; +} - if (package_path.empty()) - { - // No MSI version detected - return true; - } +void ShowNewVersionAvailable(const new_version_download_info& info) +{ + remove_toasts_by_tag(UPDATING_PROCESS_TOAST_TAG); - if (!updating::offer_msi_uninstallation(Strings)) - { - // User declined to uninstall or opted for "Don't show again" - return false; - } - auto sei = launch_action_runner(L"-uninstall_msi"); + toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; + std::wstring contents = GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_AVAILABLE); + contents += L'\n'; + contents += CurrentVersionToNextVersion(info); - WaitForSingleObject(sei.hProcess, INFINITE); - DWORD exit_code = 0; - GetExitCodeProcess(sei.hProcess, &exit_code); - CloseHandle(sei.hProcess); - return exit_code == 0; + show_toast_with_activations(std::move(contents), + GET_RESOURCE_STRING(IDS_TOAST_TITLE), + {}, + { link_button{ GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_UPDATE_NOW), + L"powertoys://update_now/" }, + link_button{ GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_MORE_INFO), + L"powertoys://open_settings/" } }, + std::move(toast_params)); +} + +void ShowOpenSettingsForUpdate() +{ + remove_toasts_by_tag(UPDATING_PROCESS_TOAST_TAG); + + toast_params toast_params{ UPDATING_PROCESS_TOAST_TAG, false }; + + std::vector actions = { + link_button{ GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_MORE_INFO), + L"powertoys://open_settings/" }, + }; + show_toast_with_activations(GET_RESOURCE_STRING(IDS_GITHUB_NEW_VERSION_AVAILABLE), + GET_RESOURCE_STRING(IDS_TOAST_TITLE), + {}, + std::move(actions), + std::move(toast_params)); +} + +SHELLEXECUTEINFOW LaunchPowerToysUpdate(const wchar_t* cmdline) +{ + std::wstring powertoysUpdaterPath; + powertoysUpdaterPath = get_module_folderpath(); + + powertoysUpdaterPath += L"\\PowerToys.Update.exe"; + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS }; + sei.lpFile = powertoysUpdaterPath.c_str(); + sei.nShow = SW_SHOWNORMAL; + sei.lpParameters = cmdline; + ShellExecuteExW(&sei); + return sei; } using namespace updating; -bool could_be_costly_connection() +bool IsMeteredConnection() { using namespace winrt::Windows::Networking::Connectivity; ConnectionProfile internetConnectionProfile = NetworkInformation::GetInternetConnectionProfile(); return internetConnectionProfile && internetConnectionProfile.IsWwanConnectionProfile(); } -void process_new_version_info(const github_version_info& version_info, - UpdateState& state, - const bool download_update, - const bool show_notifications) +void ProcessNewVersionInfo(const github_version_info& version_info, + UpdateState& state, + const bool download_update, + const bool show_notifications) { state.githubUpdateLastCheckedDate.emplace(timeutil::now()); if (std::holds_alternative(version_info)) @@ -89,7 +127,7 @@ void process_new_version_info(const github_version_info& version_info, state.downloadedInstallerFilename = new_version_info.installer_filename; if (show_notifications) { - notifications::show_new_version_available(new_version_info, Strings); + ShowNewVersionAvailable(new_version_info); } } else @@ -106,12 +144,12 @@ void process_new_version_info(const github_version_info& version_info, state.downloadedInstallerFilename = {}; if (show_notifications) { - notifications::show_open_settings_for_update(Strings); + ShowOpenSettingsForUpdate(); } } } -void periodic_update_worker() +void PeriodicUpdateWorker() { for (;;) { @@ -129,15 +167,15 @@ void periodic_update_worker() std::this_thread::sleep_for(std::chrono::minutes{ sleep_minutes_till_next_update }); - const bool download_update = !could_be_costly_connection() && get_general_settings().downloadUpdatesAutomatically; + const bool download_update = !IsMeteredConnection() && get_general_settings().downloadUpdatesAutomatically; bool version_info_obtained = false; try { - const auto new_version_info = get_github_version_info_async(Strings).get(); + const auto new_version_info = get_github_version_info_async().get(); if (new_version_info.has_value()) { version_info_obtained = true; - process_new_version_info(*new_version_info, state, download_update, true); + ProcessNewVersionInfo(*new_version_info, state, download_update, true); } else { @@ -162,27 +200,27 @@ void periodic_update_worker() } } -void check_for_updates_settings_callback() +void CheckForUpdatesCallback() { Logger::trace(L"Check for updates callback invoked"); auto state = UpdateState::read(); try { - auto new_version_info = get_github_version_info_async(Strings).get(); + auto new_version_info = get_github_version_info_async().get(); if (!new_version_info) { // If we couldn't get a new version from github for some reason, assume we're up to date, but also log error new_version_info = version_up_to_date{}; Logger::error(L"Couldn't obtain version info from github: {}", new_version_info.error()); } - const bool download_update = !could_be_costly_connection() && get_general_settings().downloadUpdatesAutomatically; - process_new_version_info(*new_version_info, state, download_update, false); + const bool download_update = !IsMeteredConnection() && get_general_settings().downloadUpdatesAutomatically; + ProcessNewVersionInfo(*new_version_info, state, download_update, false); UpdateState::store([&](UpdateState& v) { v = std::move(state); }); } catch (...) { - Logger::error("check_for_updates_settings_callback: error while processing version info"); + Logger::error("CheckForUpdatesCallback: error while processing version info"); } } diff --git a/src/runner/action_runner_utils.h b/src/runner/UpdateUtils.h similarity index 76% rename from src/runner/action_runner_utils.h rename to src/runner/UpdateUtils.h index c1b5b795a..8de3a546e 100644 --- a/src/runner/action_runner_utils.h +++ b/src/runner/UpdateUtils.h @@ -1,9 +1,9 @@ #pragma once -#define WIN32_LEAN_AND_MEAN -#include +#include -SHELLEXECUTEINFOW launch_action_runner(const wchar_t* cmdline); +void PeriodicUpdateWorker(); +void CheckForUpdatesCallback(); namespace cmdArg { @@ -16,8 +16,7 @@ namespace cmdArg const inline wchar_t* UPDATE_STAGE2_RESTART_PT = L"restart"; const inline wchar_t* UPDATE_STAGE2_DONT_START_PT = L"dont_start"; - const inline wchar_t* UNINSTALL_MSI = L"-uninstall_msi"; - const inline wchar_t* RUN_NONELEVATED = L"-run-non-elevated"; - const inline wchar_t* UPDATE_REPORT_SUCCESS = L"-report_update_success"; } + +SHELLEXECUTEINFOW LaunchPowerToysUpdate(const wchar_t* cmdline); \ No newline at end of file diff --git a/src/runner/action_runner_utils.cpp b/src/runner/action_runner_utils.cpp deleted file mode 100644 index e4d734416..000000000 --- a/src/runner/action_runner_utils.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "pch.h" - -#include "action_runner_utils.h" - -#include -#include - -SHELLEXECUTEINFOW launch_action_runner(const wchar_t* cmdline) -{ - std::wstring action_runner_path; - if (winstore::running_as_packaged()) - { - action_runner_path = winrt::Windows::ApplicationModel::Package::Current().InstalledLocation().Path(); - } - else - { - action_runner_path = get_module_folderpath(); - } - - action_runner_path += L"\\PowerToys.ActionRunner.exe"; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NOCLOSEPROCESS }; - sei.lpFile = action_runner_path.c_str(); - sei.nShow = SW_SHOWNORMAL; - sei.lpParameters = cmdline; - ShellExecuteExW(&sei); - return sei; -} diff --git a/src/runner/general_settings.cpp b/src/runner/general_settings.cpp index d46398fa7..e4faf98dc 100644 --- a/src/runner/general_settings.cpp +++ b/src/runner/general_settings.cpp @@ -6,7 +6,6 @@ #include #include "powertoy_module.h" #include -#include #include "trace.h" #include @@ -22,7 +21,6 @@ json::JsonObject GeneralSettings::to_json() { json::JsonObject result; - result.SetNamedValue(L"packaged", json::value(isPackaged)); result.SetNamedValue(L"startup", json::value(isStartupEnabled)); if (!startupDisabledReason.empty()) { @@ -65,7 +63,6 @@ GeneralSettings get_general_settings() { const bool is_user_admin = check_user_is_admin(); GeneralSettings settings{ - .isPackaged = winstore::running_as_packaged(), .isElevated = is_process_elevated(), .isRunElevated = run_as_elevated, .isAdmin = is_user_admin, @@ -75,31 +72,7 @@ GeneralSettings get_general_settings() .powerToysVersion = get_product_version() }; - if (winstore::running_as_packaged()) - { - const auto task_state = winstore::get_startup_task_status_async().get(); - switch (task_state) - { - case winstore::StartupTaskState::Disabled: - settings.isStartupEnabled = false; - break; - case winstore::StartupTaskState::Enabled: - settings.isStartupEnabled = true; - break; - case winstore::StartupTaskState::DisabledByPolicy: - settings.startupDisabledReason = GET_RESOURCE_STRING(IDS_STARTUP_DISABLED_BY_POLICY); - settings.isStartupEnabled = false; - break; - case winstore::StartupTaskState::DisabledByUser: - settings.startupDisabledReason = GET_RESOURCE_STRING(IDS_STARTUP_DISABLED_BY_USER); - settings.isStartupEnabled = false; - break; - } - } - else - { - settings.isStartupEnabled = is_auto_start_task_active_for_this_user(); - } + settings.isStartupEnabled = is_auto_start_task_active_for_this_user(); for (auto& [name, powertoy] : modules()) { @@ -118,40 +91,33 @@ void apply_general_settings(const json::JsonObject& general_configs, bool save) if (json::has(general_configs, L"startup", json::JsonValueType::Boolean)) { const bool startup = general_configs.GetNamedBoolean(L"startup"); - if (winstore::running_as_packaged()) + if (startup) { - winstore::switch_startup_task_state_async(startup).wait(); - } - else - { - if (startup) + if (is_process_elevated()) { - if (is_process_elevated()) - { - delete_auto_start_task_for_this_user(); - create_auto_start_task_for_this_user(general_configs.GetNamedBoolean(L"run_elevated", false)); - } - else - { - if (!is_auto_start_task_active_for_this_user()) - { - delete_auto_start_task_for_this_user(); - create_auto_start_task_for_this_user(false); - - run_as_elevated = false; - } - else if (!general_configs.GetNamedBoolean(L"run_elevated", false)) - { - delete_auto_start_task_for_this_user(); - create_auto_start_task_for_this_user(false); - } - } + delete_auto_start_task_for_this_user(); + create_auto_start_task_for_this_user(general_configs.GetNamedBoolean(L"run_elevated", false)); } else { - delete_auto_start_task_for_this_user(); + if (!is_auto_start_task_active_for_this_user()) + { + delete_auto_start_task_for_this_user(); + create_auto_start_task_for_this_user(false); + + run_as_elevated = false; + } + else if (!general_configs.GetNamedBoolean(L"run_elevated", false)) + { + delete_auto_start_task_for_this_user(); + create_auto_start_task_for_this_user(false); + } } } + else + { + delete_auto_start_task_for_this_user(); + } } if (json::has(general_configs, L"enabled")) { diff --git a/src/runner/general_settings.h b/src/runner/general_settings.h index f0b51733c..5cbe1fefa 100644 --- a/src/runner/general_settings.h +++ b/src/runner/general_settings.h @@ -4,7 +4,6 @@ struct GeneralSettings { - bool isPackaged; bool isStartupEnabled; std::wstring startupDisabledReason; std::map isModulesEnabledMap; diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 27702354b..73281c826 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -22,10 +22,9 @@ #include #include #include -#include -#include "update_utils.h" -#include "action_runner_utils.h" +#include "UpdateUtils.h" +#include "ActionRunnerUtils.h" #include @@ -45,8 +44,6 @@ #include #include -extern updating::notifications::strings Strings; - namespace { const wchar_t PT_URI_PROTOCOL_SCHEME[] = L"powertoys://"; @@ -120,26 +117,15 @@ int runner(bool isProcessElevated, bool openSettings, bool openOobe) debug_verify_launcher_assets(); std::thread{ [] { - periodic_update_worker(); + PeriodicUpdateWorker(); } }.detach(); - if (winstore::running_as_packaged()) - { - std::thread{ [] { - start_msi_uninstallation_sequence(); - } }.detach(); - } - else - { - std::thread{ [] { - if (updating::uninstall_previous_msix_version_async().get()) - { - notifications::show_toast(GET_RESOURCE_STRING(IDS_OLDER_MSIX_UNINSTALLED).c_str(), L"PowerToys"); - } - } }.detach(); - } - - notifications::register_background_toast_handler(); + std::thread{ [] { + if (updating::uninstall_previous_msix_version_async().get()) + { + notifications::show_toast(GET_RESOURCE_STRING(IDS_OLDER_MSIX_UNINSTALLED).c_str(), L"PowerToys"); + } + } }.detach(); chdir_current_executable(); // Load Powertoys DLLs @@ -258,7 +244,7 @@ toast_notification_handler_result toast_notification_handler(const std::wstring_ else if (param.starts_with(update_now)) { std::wstring args{ cmdArg::UPDATE_NOW_LAUNCH_STAGE1 }; - launch_action_runner(args.c_str()); + LaunchPowerToysUpdate(args.c_str()); return toast_notification_handler_result::exit_success; } else if (param == couldnt_toggle_powerpreview_modules_disable) diff --git a/src/runner/runner.vcxproj b/src/runner/runner.vcxproj index 052fe88b6..7c1253912 100644 --- a/src/runner/runner.vcxproj +++ b/src/runner/runner.vcxproj @@ -46,7 +46,6 @@ - @@ -62,17 +61,17 @@ - + - + - + @@ -111,9 +110,6 @@ {17da04df-e393-4397-9cf0-84dabe11032e} - - {c502a854-53ac-4ebb-8dc0-e4af2191e4f6} - diff --git a/src/runner/runner.vcxproj.filters b/src/runner/runner.vcxproj.filters index 65337bf1d..66f157402 100644 --- a/src/runner/runner.vcxproj.filters +++ b/src/runner/runner.vcxproj.filters @@ -27,10 +27,7 @@ Utils - - Utils - - + Utils @@ -72,10 +69,10 @@ Utils - + Utils - + Utils diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 84d99cdb5..839de4167 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -9,7 +9,7 @@ #include "tray_icon.h" #include "general_settings.h" #include "restart_elevated.h" -#include "update_utils.h" +#include "UpdateUtils.h" #include "centralized_kb_hook.h" #include @@ -84,7 +84,7 @@ std::optional dispatch_json_action_to_module(const json::JsonObjec } else if (action == L"check_for_updates") { - check_for_updates_settings_callback(); + CheckForUpdatesCallback(); } else if (action == L"request_update_state_date") { diff --git a/src/runner/update_utils.h b/src/runner/update_utils.h deleted file mode 100644 index e1632c7b2..000000000 --- a/src/runner/update_utils.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -bool start_msi_uninstallation_sequence(); -void periodic_update_worker(); -void check_for_updates_settings_callback(); diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/GeneralSettings.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/GeneralSettings.cs index 9c062e9bd..0c43a3cff 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/GeneralSettings.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/GeneralSettings.cs @@ -13,10 +13,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library { public class GeneralSettings : ISettingsConfig { - // Gets or sets a value indicating whether packaged. - [JsonPropertyName("packaged")] - public bool Packaged { get; set; } - // Gets or sets a value indicating whether run powertoys on start-up. [JsonPropertyName("startup")] public bool Startup { get; set; } @@ -57,7 +53,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library [SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Any error from calling interop code should not prevent the program from loading.")] public GeneralSettings() { - Packaged = false; Startup = false; IsAdmin = false; IsElevated = false; diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/GeneralViewModel.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/GeneralViewModel.cs index bbe68746c..a89b46e6d 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/GeneralViewModel.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/ViewModels/GeneralViewModel.cs @@ -112,7 +112,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels } } - private bool _packaged; private bool _startup; private bool _isElevated; private bool _runElevated; @@ -130,24 +129,6 @@ namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels private bool _isNewVersionDownloading; private bool _isNewVersionChecked; - // Gets or sets a value indicating whether packaged. - public bool Packaged - { - get - { - return _packaged; - } - - set - { - if (_packaged != value) - { - _packaged = value; - NotifyPropertyChanged(); - } - } - } - // Gets or sets a value indicating whether run powertoys on start-up. public bool Startup { diff --git a/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs index 8aef0f8e1..9293f222f 100644 --- a/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs +++ b/src/settings-ui/Microsoft.PowerToys.Settings.UI.UnitTests/ViewModelTests/General.cs @@ -61,7 +61,6 @@ namespace ViewModelTests // Verify that the old settings persisted Assert.AreEqual(originalGeneralSettings.AutoDownloadUpdates, viewModel.AutoDownloadUpdates); - Assert.AreEqual(originalGeneralSettings.Packaged, viewModel.Packaged); Assert.AreEqual(originalGeneralSettings.PowertoysVersion, viewModel.PowerToysVersion); Assert.AreEqual(originalGeneralSettings.RunElevated, viewModel.RunElevated); Assert.AreEqual(originalGeneralSettings.Startup, viewModel.Startup);