From 72a338459fb00d2cdc407b9e9316a7dc6cf22408 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Tue, 25 May 2021 18:19:26 +0300 Subject: [PATCH 1/9] [Updating] Create a dedicated executable project for updating procedures --- .pipelines/pipeline.user.windows.yml | 1 + PowerToys.sln | 6 + installer/PowerToysSetup/Product.wxs | 4 + src/ActionRunner/actionRunner.cpp | 237 ----------------------- src/ActionRunner/actionRunner.vcxproj | 6 - src/Update/LocProject.json | 14 ++ src/Update/PowerToys.Update.base.rc | 36 ++++ src/Update/PowerToys.Update.cpp | 258 ++++++++++++++++++++++++++ src/Update/PowerToys.Update.vcxproj | 76 ++++++++ src/Update/Resources.resx | 91 +++++++++ src/Update/packages.config | 4 + src/Update/resource.base.h | 11 ++ src/common/logger/logger_settings.h | 2 + src/common/utils/elevation.h | 3 + src/runner/action_runner_utils.h | 1 - 15 files changed, 506 insertions(+), 244 deletions(-) create mode 100644 src/Update/LocProject.json create mode 100644 src/Update/PowerToys.Update.base.rc create mode 100644 src/Update/PowerToys.Update.cpp create mode 100644 src/Update/PowerToys.Update.vcxproj create mode 100644 src/Update/Resources.resx create mode 100644 src/Update/packages.config create mode 100644 src/Update/resource.base.h diff --git a/.pipelines/pipeline.user.windows.yml b/.pipelines/pipeline.user.windows.yml index a87d40cf91a6..27c6b3bebb60 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 de55865c0430..5ac58a605a43 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -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 @@ -703,6 +705,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 diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs index 9a7cbf205de1..9cced7747628 100644 --- a/installer/PowerToysSetup/Product.wxs +++ b/installer/PowerToysSetup/Product.wxs @@ -359,6 +359,9 @@ + + + @@ -869,6 +872,7 @@ + diff --git a/src/ActionRunner/actionRunner.cpp b/src/ActionRunner/actionRunner.cpp index bfd54f816b0f..d388db4ff78b 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(); - 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 126508090e42..04855caae0b2 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 000000000000..c4ca89a4a486 --- /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 000000000000..5e4e3aab3c66 --- /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 000000000000..226f3513bd18 --- /dev/null +++ b/src/Update/PowerToys.Update.cpp @@ -0,0 +1,258 @@ +// 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 + +#include "../runner/tray_icon.h" +#include "../runner/action_runner_utils.h" + +auto Strings = create_notifications_strings(); + +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(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; + 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 000000000000..76d0f4464238 --- /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 000000000000..7e2feb1971a8 --- /dev/null +++ b/src/Update/Resources.resx @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 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/Update/packages.config b/src/Update/packages.config new file mode 100644 index 000000000000..81f107b8bcab --- /dev/null +++ b/src/Update/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/src/Update/resource.base.h b/src/Update/resource.base.h new file mode 100644 index 000000000000..eaef55651343 --- /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/logger/logger_settings.h b/src/common/logger/logger_settings.h index 995c50ee8a9c..d4ea19a40f64 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/utils/elevation.h b/src/common/utils/elevation.h index 39710c1a9d1a..0fef3dc84c98 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/action_runner_utils.h b/src/runner/action_runner_utils.h index c1b5b795a8fa..1d24d127de8d 100644 --- a/src/runner/action_runner_utils.h +++ b/src/runner/action_runner_utils.h @@ -16,7 +16,6 @@ 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"; From 5b286d90c23e6cf4e8ff30a982a24b3b72429d24 Mon Sep 17 00:00:00 2001 From: Andrey Nekrasov Date: Thu, 27 May 2021 16:56:03 +0300 Subject: [PATCH 2/9] [Updating] Use PowerToys.Update for update procedures (#11495) * [Updating] Use PowerToys.Update for update procedures * fixup: review comments --- .../bootstrapper/bootstrapper.cpp | 6 +- src/Update/PowerToys.Update.cpp | 2 +- src/common/updating/installer.cpp | 20 +------ src/common/updating/installer.h | 2 +- src/runner/ActionRunnerUtils.h | 9 +++ .../{update_utils.cpp => UpdateUtils.cpp} | 56 ++++++++----------- .../{action_runner_utils.h => UpdateUtils.h} | 10 ++-- src/runner/action_runner_utils.cpp | 28 ---------- src/runner/main.cpp | 35 ++++++------ src/runner/runner.vcxproj | 7 +-- src/runner/runner.vcxproj.filters | 9 +-- src/runner/settings_window.cpp | 4 +- src/runner/update_utils.h | 7 --- 13 files changed, 68 insertions(+), 127 deletions(-) create mode 100644 src/runner/ActionRunnerUtils.h rename src/runner/{update_utils.cpp => UpdateUtils.cpp} (78%) rename src/runner/{action_runner_utils.h => UpdateUtils.h} (81%) delete mode 100644 src/runner/action_runner_utils.cpp delete mode 100644 src/runner/update_utils.h diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index 02eb38102f2d..246119db396c 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -4,7 +4,6 @@ #include "RcResource.h" #include #include -#include #include #include #include @@ -14,11 +13,8 @@ #include #include -#include - #include "progressbar_window.h" -auto Strings = create_notifications_strings(); static bool g_Silent = false; #define STR_HELPER(x) #x @@ -351,7 +347,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() && !updating::uninstall_msi_version(package_path)) { spdlog::error("Couldn't install the existing MSI package ({})", GetLastError()); ShowMessageBoxError(IDS_UNINSTALL_PREVIOUS_VERSION_ERROR); diff --git a/src/Update/PowerToys.Update.cpp b/src/Update/PowerToys.Update.cpp index 226f3513bd18..87ed480fc2c6 100644 --- a/src/Update/PowerToys.Update.cpp +++ b/src/Update/PowerToys.Update.cpp @@ -31,7 +31,7 @@ #include #include "../runner/tray_icon.h" -#include "../runner/action_runner_utils.h" +#include "../runner/UpdateUtils.h" auto Strings = create_notifications_strings(); diff --git a/src/common/updating/installer.cpp b/src/common/updating/installer.cpp index 91572d0dde1a..403ea1022005 100644 --- a/src/common/updating/installer.cpp +++ b/src/common/updating/installer.cpp @@ -2,6 +2,7 @@ #include "installer.h" #include +// TODO: remove; do not depend on toasts #include #include #include "utils/winapi_error.h" @@ -66,25 +67,10 @@ namespace updating return selection == IDYES; } - bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings& strings) + bool uninstall_msi_version(const std::wstring& package_path) { 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; + return ERROR_SUCCESS == uninstall_result; } std::optional get_msi_package_installed_path() diff --git a/src/common/updating/installer.h b/src/common/updating/installer.h index 0da895248238..02cbdcf4ce1f 100644 --- a/src/common/updating/installer.h +++ b/src/common/updating/installer.h @@ -10,7 +10,7 @@ namespace updating { std::wstring get_msi_package_path(); - bool uninstall_msi_version(const std::wstring& package_path, const notifications::strings&); + bool uninstall_msi_version(const std::wstring& package_path); bool offer_msi_uninstallation(const notifications::strings&); std::optional get_msi_package_installed_path(); diff --git a/src/runner/ActionRunnerUtils.h b/src/runner/ActionRunnerUtils.h new file mode 100644 index 000000000000..a0c59761c6f7 --- /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/update_utils.cpp b/src/runner/UpdateUtils.cpp similarity index 78% rename from src/runner/update_utils.cpp rename to src/runner/UpdateUtils.cpp index 4c49592dde06..a1f35eb94170 100644 --- a/src/runner/update_utils.cpp +++ b/src/runner/UpdateUtils.cpp @@ -2,15 +2,16 @@ #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 @@ -22,40 +23,31 @@ namespace constexpr int64_t UPDATE_CHECK_AFTER_FAILED_INTERVAL_MINUTES = 60 * 2; } -bool start_msi_uninstallation_sequence() +SHELLEXECUTEINFOW LaunchPowerToysUpdate(const wchar_t* cmdline) { - const auto package_path = updating::get_msi_package_path(); - - if (package_path.empty()) - { - // No MSI version detected - return true; - } - - 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"); - - WaitForSingleObject(sei.hProcess, INFINITE); - DWORD exit_code = 0; - GetExitCodeProcess(sei.hProcess, &exit_code); - CloseHandle(sei.hProcess); - return exit_code == 0; + 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, +void ProcessNewVersionInfo(const github_version_info& version_info, UpdateState& state, const bool download_update, const bool show_notifications) @@ -111,7 +103,7 @@ void process_new_version_info(const github_version_info& version_info, } } -void periodic_update_worker() +void PeriodicUpdateWorker() { for (;;) { @@ -129,7 +121,7 @@ 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 { @@ -137,7 +129,7 @@ void periodic_update_worker() 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,7 +154,7 @@ void periodic_update_worker() } } -void check_for_updates_settings_callback() +void CheckForUpdatesCallback() { Logger::trace(L"Check for updates callback invoked"); auto state = UpdateState::read(); @@ -175,14 +167,14 @@ void check_for_updates_settings_callback() 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 81% rename from src/runner/action_runner_utils.h rename to src/runner/UpdateUtils.h index 1d24d127de8d..688cf9e70f7e 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 CheckForUpdatesSettingsCallback(); namespace cmdArg { @@ -16,7 +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* 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 e4d73441665f..000000000000 --- 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/main.cpp b/src/runner/main.cpp index 27702354bf9d..005a6f914dc7 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -24,8 +24,8 @@ #include #include -#include "update_utils.h" -#include "action_runner_utils.h" +#include "UpdateUtils.h" +#include "ActionRunnerUtils.h" #include @@ -120,24 +120,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(); - } + 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(); @@ -258,7 +249,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) @@ -276,6 +267,12 @@ toast_notification_handler_result toast_notification_handler(const std::wstring_ } } +// TODO: dummy function to be removed to avoid conflicts with https://github.com/microsoft/PowerToys/pull/11450 +bool start_msi_uninstallation_sequence() +{ + return true; +} + int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { winrt::init_apartment(); diff --git a/src/runner/runner.vcxproj b/src/runner/runner.vcxproj index 052fe88b614c..cc786f8ef3d2 100644 --- a/src/runner/runner.vcxproj +++ b/src/runner/runner.vcxproj @@ -46,7 +46,6 @@ - @@ -62,17 +61,17 @@ - + - + - + diff --git a/src/runner/runner.vcxproj.filters b/src/runner/runner.vcxproj.filters index 65337bf1d075..66f157402590 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 84d99cdb5951..1bef7af64600 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(); + CheckForUpdatesSettingsCallback(); } 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 e1632c7b2189..000000000000 --- 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(); From f526fabc54ca5bebf19fbd930bcce15a83205fc0 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Fri, 28 May 2021 23:55:18 +0300 Subject: [PATCH 3/9] [Setup] Remove toast notifications and other dependencies from bootstrapper --- PowerToys.sln | 2 + .../PowerToysBootstrapper.sln | 18 - .../bootstrapper/DotnetInstallation.cpp | 9 +- .../bootstrapper/DotnetInstallation.h | 0 .../bootstrapper/bootstrapper.cpp | 784 +++++++++--------- .../bootstrapper/bootstrapper.vcxproj | 17 +- .../PowerToysBootstrapper/bootstrapper/pch.h | 3 + .../bootstrapper/progressbar_window.cpp | 1 - .../CustomAction.cpp | 3 +- src/ActionRunner/actionRunner.cpp | 2 +- src/Update/PowerToys.Update.cpp | 7 +- src/common/updating/http_client.cpp | 66 -- src/common/updating/http_client.h | 19 - src/common/updating/installer.cpp | 137 +-- src/common/updating/installer.h | 7 - src/common/updating/notifications.cpp | 61 -- src/common/updating/notifications.h | 40 - src/common/updating/updating.cpp | 6 +- src/common/updating/updating.h | 3 +- src/common/updating/updating.vcxproj | 9 - src/common/updating/updating.vcxproj.filters | 22 +- src/common/utils/HttpClient.h | 79 ++ src/common/utils/MsiUtils.h | 95 +++ src/runner/UpdateUtils.cpp | 66 +- src/runner/UpdateUtils.h | 2 +- src/runner/main.cpp | 2 - src/runner/settings_window.cpp | 2 +- 27 files changed, 680 insertions(+), 782 deletions(-) rename src/common/updating/dotnet_installation.cpp => installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.cpp (95%) rename src/common/updating/dotnet_installation.h => installer/PowerToysBootstrapper/bootstrapper/DotnetInstallation.h (100%) delete mode 100644 src/common/updating/http_client.h delete mode 100644 src/common/updating/notifications.cpp delete mode 100644 src/common/updating/notifications.h create mode 100644 src/common/utils/HttpClient.h create mode 100644 src/common/utils/MsiUtils.h diff --git a/PowerToys.sln b/PowerToys.sln index 5ac58a605a43..029a0fca3ea5 100644 --- a/PowerToys.sln +++ b/PowerToys.sln @@ -288,8 +288,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 diff --git a/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln b/installer/PowerToysBootstrapper/PowerToysBootstrapper.sln index 2096d0c9a79a..8f25336454e6 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 30cdd9697e3c..7647dc143f82 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/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index 246119db396c..e4326c265a86 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -2,17 +2,18 @@ #include "Generated Files/resource.h" #include "RcResource.h" -#include -#include +#include #include #include #include +#include #include #include #include #include #include +#include "DotnetInstallation.h" #include "progressbar_window.h" static bool g_Silent = false; @@ -22,9 +23,9 @@ static bool g_Silent = false; namespace // Strings in this namespace should not be localized { - const wchar_t APPLICATION_ID[] = L"PowerToysInstaller"; - const char EXE_LOG_FILENAME[] = "powertoys-bootstrapper-exe-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; - const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; + const wchar_t APPLICATION_ID[] = L"PowerToysInstaller"; + const char EXE_LOG_FILENAME[] = "powertoys-bootstrapper-exe-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; + const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; } #undef STR @@ -34,440 +35,481 @@ namespace fs = std::filesystem; std::optional ExtractEmbeddedInstaller(const fs::path extractPath) { - auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN"); - if (!executableRes) - { - return std::nullopt; - } - - auto installerPath = extractPath / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi"; - return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt; + auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN"); + if (!executableRes) + { + return std::nullopt; + } + + auto installerPath = extractPath / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi"; + return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt; } void SetupLogger(fs::path directory, const spdlog::level::level_enum severity) { - std::shared_ptr logger; - auto nullLogger = spdlog::null_logger_mt("null"); - try + std::shared_ptr logger; + auto nullLogger = spdlog::null_logger_mt("null"); + try + { + if (severity != spdlog::level::off) { - if (severity != spdlog::level::off) - { - logger = spdlog::basic_logger_mt("file", (directory / EXE_LOG_FILENAME).wstring()); - - std::error_code _; - const DWORD msiSev = severity == spdlog::level::debug ? INSTALLLOGMODE_VERBOSE : INSTALLLOGMODE_ERROR; - const auto msiLogPath = directory / MSI_LOG_FILENAME; - MsiEnableLogW(msiSev, msiLogPath.c_str(), INSTALLLOGATTRIBUTES_APPEND); - } - else - { - logger = nullLogger; - } + logger = spdlog::basic_logger_mt("file", (directory / EXE_LOG_FILENAME).wstring()); - logger->set_pattern("[%L][%d-%m-%C-%T] %v"); - logger->set_level(severity); - spdlog::set_default_logger(std::move(logger)); - spdlog::set_level(severity); - spdlog::flush_every(std::chrono::seconds(5)); + std::error_code _; + const DWORD msiSev = severity == spdlog::level::debug ? INSTALLLOGMODE_VERBOSE : INSTALLLOGMODE_ERROR; + const auto msiLogPath = directory / MSI_LOG_FILENAME; + MsiEnableLogW(msiSev, msiLogPath.c_str(), INSTALLLOGATTRIBUTES_APPEND); } - catch (...) + else { - spdlog::set_default_logger(nullLogger); + logger = nullLogger; } + + logger->set_pattern("[%L][%d-%m-%C-%T] %v"); + logger->set_level(severity); + spdlog::set_default_logger(std::move(logger)); + spdlog::set_level(severity); + spdlog::flush_every(std::chrono::seconds(5)); + } + catch (...) + { + spdlog::set_default_logger(nullLogger); + } } void CleanupSettingsFromOlderVersions() { - try + try + { + const auto logSettingsFile = fs::path{ PTSettingsHelper::get_root_save_folder_location() } / PTSettingsHelper::log_settings_filename; + if (fs::is_regular_file(logSettingsFile)) { - const auto logSettingsFile = fs::path{ PTSettingsHelper::get_root_save_folder_location() } / PTSettingsHelper::log_settings_filename; - if (fs::is_regular_file(logSettingsFile)) - { - fs::remove(logSettingsFile); - spdlog::info("Removed old log settings file"); - } - else - { - spdlog::info("Old log settings file wasn't found"); - } + fs::remove(logSettingsFile); + spdlog::info("Removed old log settings file"); } - catch(...) + else { - spdlog::error("Failed to cleanup old log settings"); + spdlog::info("Old log settings file wasn't found"); } + } + catch (...) + { + spdlog::error("Failed to cleanup old log settings"); + } } 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); - } + if (!g_Silent) + { + MessageBoxW(nullptr, + message, + GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), + MB_OK | MB_ICONERROR); + } } void ShowMessageBoxError(const UINT messageId) { - ShowMessageBoxError(GET_RESOURCE_STRING(messageId).c_str()); + ShowMessageBoxError(GET_RESOURCE_STRING(messageId).c_str()); } -int Bootstrapper(HINSTANCE hInstance) +bool uninstall_msi_version(const std::wstring& package_path) { - winrt::init_apartment(); - char* programFilesDir = nullptr; - size_t size = 0; - std::string defaultInstallDir; + const auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); + return ERROR_SUCCESS == uninstall_result; +} - if (!_dupenv_s(&programFilesDir, &size, "PROGRAMFILES")) - { - defaultInstallDir += programFilesDir; - defaultInstallDir += "\\PowerToys"; - } +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 }; +} - 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."); - // clang-format on - - cxxopts::ParseResult cmdArgs; - bool showHelp = false; - try - { - cmdArgs = options.parse(__argc, const_cast(__argv)); - } - catch (...) - { - showHelp = true; - } - showHelp = showHelp || cmdArgs["help"].as(); - if (showHelp) - { - std::ostringstream helpMsg; - helpMsg << options.help(); - MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION); - return 0; +int Bootstrapper(HINSTANCE hInstance) +{ + winrt::init_apartment(); + char* programFilesDir = nullptr; + size_t size = 0; + std::string defaultInstallDir; + + if (!_dupenv_s(&programFilesDir, &size, "PROGRAMFILES")) + { + defaultInstallDir += programFilesDir; + defaultInstallDir += "\\PowerToys"; + } + + 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."); + // clang-format on + + cxxopts::ParseResult cmdArgs; + bool showHelp = false; + try + { + cmdArgs = options.parse(__argc, const_cast(__argv)); + } + catch (...) + { + showHelp = true; + } + + showHelp = showHelp || cmdArgs["help"].as(); + if (showHelp) + { + std::ostringstream helpMsg; + helpMsg << options.help(); + MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION); + return 0; + } + + g_Silent = cmdArgs["silent"].as(); + const bool noFullUI = cmdArgs["no_full_ui"].as(); + const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].as(); + const bool noStartPT = cmdArgs["no_start_pt"].as(); + const bool startPT = cmdArgs["start_pt"].as(); + const auto logLevel = cmdArgs["log_level"].as(); + const auto logDirArg = cmdArgs["log_dir"].as(); + const auto installDirArg = cmdArgs["install_dir"].as(); + const bool extractMsiOnly = cmdArgs["extract_msi"].as(); + + std::wstring installFolderProp; + if (!installDirArg.empty()) + { + std::string installDir; + if (installDirArg.find(' ') != std::string::npos) + { + installDir = "\"" + installDirArg + "\""; } - - g_Silent = cmdArgs["silent"].as(); - const bool noFullUI = cmdArgs["no_full_ui"].as(); - const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].as(); - const bool noStartPT = cmdArgs["no_start_pt"].as(); - const bool startPT = cmdArgs["start_pt"].as(); - const auto logLevel = cmdArgs["log_level"].as(); - const auto logDirArg = cmdArgs["log_dir"].as(); - const auto installDirArg = cmdArgs["install_dir"].as(); - const bool extractMsiOnly = cmdArgs["extract_msi"].as(); - - std::wstring installFolderProp; - if (!installDirArg.empty()) + else { - std::string installDir; - if (installDirArg.find(' ') != std::string::npos) - { - installDir = "\"" + installDirArg + "\""; - } - else - { - installDir = installDirArg; - } - - installFolderProp = std::wstring(installDir.length(), L' '); - std::copy(installDir.begin(), installDir.end(), installFolderProp.begin()); - installFolderProp = L"INSTALLFOLDER=" + installFolderProp; + installDir = installDirArg; } - fs::path logDir = "."; - try - { - fs::path logDirArgPath = logDirArg; - if (fs::exists(logDirArgPath) && fs::is_directory(logDirArgPath)) - { - logDir = logDirArgPath; - } - } - catch (...) - { - } + installFolderProp = std::wstring(installDir.length(), L' '); + std::copy(installDir.begin(), installDir.end(), installFolderProp.begin()); + installFolderProp = L"INSTALLFOLDER=" + installFolderProp; + } - spdlog::level::level_enum severity = spdlog::level::debug; - if (logLevel == "error") + fs::path logDir = "."; + try + { + fs::path logDirArgPath = logDirArg; + if (fs::exists(logDirArgPath) && fs::is_directory(logDirArgPath)) { - severity = spdlog::level::err; + logDir = logDirArgPath; } + } + catch (...) + { + } - SetupLogger(logDir, severity); - spdlog::debug("PowerToys Bootstrapper is launched\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, g_Silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extractMsiOnly); + spdlog::level::level_enum severity = spdlog::level::debug; + if (logLevel == "error") + { + severity = spdlog::level::err; + } - // If a user requested an MSI -> extract it and exit - if (extractMsiOnly) - { - if (const auto installerPath = ExtractEmbeddedInstaller(fs::current_path())) - { - spdlog::debug("MSI installer extracted to {}", installerPath->string()); - } - else - { - spdlog::error("MSI installer couldn't be extracted"); - } + SetupLogger(logDir, severity); + spdlog::debug("PowerToys Bootstrapper is launched\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, g_Silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extractMsiOnly); - return 0; - } - - const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - - // Do not support installing on Windows < 1903 - if (updating::is_1809_or_older()) + // If a user requested an MSI -> extract it and exit + if (extractMsiOnly) + { + if (const auto installerPath = ExtractEmbeddedInstaller(fs::current_path())) { - ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR); - spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString()); - return 1; + spdlog::debug("MSI installer extracted to {}", installerPath->string()); } - - // Check if there's a newer version installed - const auto installedVersion = updating::get_installed_powertoys_version(); - if (installedVersion && *installedVersion >= myVersion) + else { - spdlog::error(L"Detected a newer version {} vs {}", (*installedVersion).toWstring(), myVersion.toWstring()); - ShowMessageBoxError(IDS_NEWER_VERSION_ERROR); - return 0; + spdlog::error("MSI installer couldn't be extracted"); } - // Setup MSI UI visibility and restart as elevated if required - if (!noFullUI) + return 0; + } + + const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + + // Do not support installing on Windows < 1903 + //if (updating::is_1809_or_older()) + { + 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 = get_installed_powertoys_version(); + if (installedVersion && *installedVersion >= myVersion) + { + spdlog::error(L"Detected a newer version {} vs {}", (*installedVersion).toWstring(), myVersion.toWstring()); + ShowMessageBoxError(IDS_NEWER_VERSION_ERROR); + return 0; + } + + // Setup MSI UI visibility and restart as elevated if required + if (!noFullUI) + { + MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr); + } + + if (g_Silent) + { + if (is_process_elevated()) { - MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr); + MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr); } - - if (g_Silent) + else { - if (is_process_elevated()) + spdlog::debug("MSI doesn't support silent mode without elevation => restarting elevated"); + // MSI fails to run in silent mode due to a suppressed UAC w/o elevation, + // so we restart ourselves elevated with the same args + std::wstring params; + int nCmdArgs = 0; + LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs); + for (int i = 1; i < nCmdArgs; ++i) + { + if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos) { - MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr); + params += L'"'; + params += argList[i]; + params += L'"'; } else { - spdlog::debug("MSI doesn't support silent mode without elevation => restarting elevated"); - // MSI fails to run in silent mode due to a suppressed UAC w/o elevation, - // so we restart ourselves elevated with the same args - std::wstring params; - int nCmdArgs = 0; - LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs); - for (int i = 1; i < nCmdArgs; ++i) - { - if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos) - { - params += L'"'; - params += argList[i]; - params += L'"'; - } - else - { - params += argList[i]; - } - - if (i != nCmdArgs - 1) - { - params += L' '; - } - } - - const auto processHandle = run_elevated(argList[0], params.c_str()); - if (!processHandle) - { - spdlog::error("Couldn't restart elevated to enable silent mode! ({})", GetLastError()); - return 1; - } - - if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0) - { - DWORD exitCode = 0; - GetExitCodeProcess(processHandle, &exitCode); - return exitCode; - } - else - { - spdlog::error("Elevated setup process timed out after 60m => using basic MSI UI ({})", GetLastError()); - // Couldn't install using the completely silent mode in an hour, use basic UI. - TerminateProcess(processHandle, 0); - MsiSetInternalUI(INSTALLUILEVEL_BASIC, nullptr); - } + params += argList[i]; } - } - - // Try killing PowerToys and prevent future processes launch by acquiring app mutex - for (auto& handle : getProcessHandlesByName(L"PowerToys.exe", PROCESS_TERMINATE)) - { - TerminateProcess(handle.get(), 0); - } - auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME); - auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME); - if (!instanceMutex) - { - spdlog::error("Couldn't acquire PowerToys global mutex. Setup couldn't terminate PowerToys.exe process"); - return 1; - } + if (i != nCmdArgs - 1) + { + params += L' '; + } + } - spdlog::debug("Extracting embedded MSI installer"); - const auto installerPath = ExtractEmbeddedInstaller(fs::temp_directory_path()); - if (!installerPath) - { - ShowMessageBoxError(IDS_INSTALLER_EXTRACT_ERROR); - spdlog::error("Couldn't install the MSI installer ({})", GetLastError()); + const auto processHandle = run_elevated(argList[0], params.c_str()); + if (!processHandle) + { + spdlog::error("Couldn't restart elevated to enable silent mode! ({})", GetLastError()); return 1; - } - - auto removeExtractedInstaller = wil::scope_exit([&] { - std::error_code _; - fs::remove(*installerPath, _); + } + + if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0) + { + DWORD exitCode = 0; + GetExitCodeProcess(processHandle, &exitCode); + return exitCode; + } + else + { + spdlog::error("Elevated setup process timed out after 60m => using basic MSI UI ({})", GetLastError()); + // Couldn't install using the completely silent mode in an hour, use basic UI. + TerminateProcess(processHandle, 0); + MsiSetInternalUI(INSTALLUILEVEL_BASIC, nullptr); + } + } + } + + // Try killing PowerToys and prevent future processes launch by acquiring app mutex + for (auto& handle : getProcessHandlesByName(L"PowerToys.exe", PROCESS_TERMINATE)) + { + TerminateProcess(handle.get(), 0); + } + + auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME); + auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME); + if (!instanceMutex) + { + spdlog::error("Couldn't acquire PowerToys global mutex. Setup couldn't terminate PowerToys.exe process"); + return 1; + } + + spdlog::debug("Extracting embedded MSI installer"); + const auto installerPath = ExtractEmbeddedInstaller(fs::temp_directory_path()); + if (!installerPath) + { + ShowMessageBoxError(IDS_INSTALLER_EXTRACT_ERROR); + spdlog::error("Couldn't install the MSI installer ({})", GetLastError()); + return 1; + } + + auto removeExtractedInstaller = wil::scope_exit([&] { + std::error_code _; + fs::remove(*installerPath, _); }); - spdlog::debug("Acquiring existing MSI package path if exists"); - const auto package_path = updating::get_msi_package_path(); - if (!package_path.empty()) - { - spdlog::debug(L"Existing MSI package path found: {}", package_path); - } - else - { - spdlog::debug("Existing MSI package path not found"); - } - - if (!package_path.empty() && !updating::uninstall_msi_version(package_path)) - { - spdlog::error("Couldn't install the existing MSI package ({})", GetLastError()); - ShowMessageBoxError(IDS_UNINSTALL_PREVIOUS_VERSION_ERROR); - return 1; - } - - const bool installDotnet = !skipDotnetInstall; - if (!g_Silent) - { - OpenProgressBarDialog(hInstance, 0, GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), GET_RESOURCE_STRING(IDS_DOWNLOADING_DOTNET).c_str()); - } - - try - { - if (installDotnet) + spdlog::debug("Acquiring existing MSI package path if exists"); + const auto package_path = GetMsiPackagePath(); + if (!package_path.empty()) + { + spdlog::debug(L"Existing MSI package path found: {}", package_path); + } + else + { + spdlog::debug("Existing MSI package path not found"); + } + + 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); + return 1; + } + + const bool installDotnet = !skipDotnetInstall; + if (!g_Silent) + { + OpenProgressBarDialog(hInstance, 0, GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), GET_RESOURCE_STRING(IDS_DOWNLOADING_DOTNET).c_str()); + } + + try + { + if (installDotnet) + { + spdlog::debug("Detecting if dotnet is installed"); + const bool dotnetInstalled = updating::dotnet_is_installed(); + spdlog::debug("Dotnet is already installed: {}", dotnetInstalled); + if (!dotnetInstalled) + { + bool installedSuccessfully = false; + if (const auto dotnet_installer_path = updating::download_dotnet()) { - spdlog::debug("Detecting if dotnet is installed"); - const bool dotnetInstalled = updating::dotnet_is_installed(); - spdlog::debug("Dotnet is already installed: {}", dotnetInstalled); - if (!dotnetInstalled) - { - bool installedSuccessfully = false; - if (const auto dotnet_installer_path = updating::download_dotnet()) - { - // Dotnet installer has its own progress bar - CloseProgressBarDialog(); - installedSuccessfully = updating::install_dotnet(*dotnet_installer_path, g_Silent); - if (!installedSuccessfully) - { - spdlog::error("Couldn't install dotnet"); - } - } - else - { - spdlog::error("Couldn't download dotnet"); - } - - if (!installedSuccessfully) - { - ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR); - } - } + // Dotnet installer has its own progress bar + CloseProgressBarDialog(); + installedSuccessfully = updating::install_dotnet(*dotnet_installer_path, g_Silent); + if (!installedSuccessfully) + { + spdlog::error("Couldn't install dotnet"); + } } - } - catch (...) - { - 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(); - - const std::wstring msiProps = installFolderProp; - spdlog::debug("Launching MSI installation for new package {}", installerPath->string()); - const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS; - if (!installationDone) - { - spdlog::error("Couldn't install new MSI package ({})", GetLastError()); - return 1; - } - - spdlog::debug("Installation completed"); - - if ((!noStartPT && !g_Silent) || startPT) - { - spdlog::debug("Starting the newly installed PowerToys.exe"); - auto newPTPath = updating::get_msi_package_installed_path(); - if (!newPTPath) + else { - spdlog::error("Couldn't determine new MSI package install location ({})", GetLastError()); - return 1; + spdlog::error("Couldn't download dotnet"); } - *newPTPath += L"\\PowerToys.exe"; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE }; - sei.lpFile = newPTPath->c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteExW(&sei); + if (!installedSuccessfully) + { + ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR); + } + } + } + } + catch (...) + { + 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(); + + const std::wstring msiProps = installFolderProp; + spdlog::debug("Launching MSI installation for new package {}", installerPath->string()); + const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS; + if (!installationDone) + { + spdlog::error("Couldn't install new MSI package ({})", GetLastError()); + return 1; + } + + spdlog::debug("Installation completed"); + + if ((!noStartPT && !g_Silent) || startPT) + { + spdlog::debug("Starting the newly installed PowerToys.exe"); + auto newPTPath = GetMsiPackageInstalledPath(); + if (!newPTPath) + { + spdlog::error("Couldn't determine new MSI package install location ({})", GetLastError()); + return 1; } - return 0; + *newPTPath += L"\\PowerToys.exe"; + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE }; + sei.lpFile = newPTPath->c_str(); + sei.nShow = SW_SHOWNORMAL; + ShellExecuteExW(&sei); + } + + return 0; } int WINAPI WinMain(HINSTANCE hi, HINSTANCE, LPSTR, int) { - try - { - return Bootstrapper(hi); - } - catch (const std::exception& ex) - { - std::string messageA{ "Unhandled std exception encountered\n" }; - messageA.append(ex.what()); - - spdlog::error(messageA.c_str()); - - std::wstring messageW{}; - std::copy(messageA.begin(), messageA.end(), messageW.begin()); - ShowMessageBoxError(messageW.c_str()); - } - catch (winrt::hresult_error const& ex) - { - std::wstring message{ L"Unhandled winrt exception encountered\n" }; - message.append(ex.message().c_str()); - - spdlog::error(message.c_str()); - - ShowMessageBoxError(message.c_str()); - } - catch (...) - { - auto lastErrorMessage = get_last_error_message(GetLastError()); - std::wstring message{ L"Unknown exception encountered\n" }; - message.append(lastErrorMessage ? std::move(*lastErrorMessage) : L""); - - spdlog::error(message.c_str()); - - ShowMessageBoxError(message.c_str()); - } - return 0; + try + { + return Bootstrapper(hi); + } + catch (const std::exception& ex) + { + std::string messageA{ "Unhandled std exception encountered\n" }; + messageA.append(ex.what()); + + spdlog::error(messageA.c_str()); + + std::wstring messageW{}; + std::copy(messageA.begin(), messageA.end(), messageW.begin()); + ShowMessageBoxError(messageW.c_str()); + } + catch (winrt::hresult_error const& ex) + { + std::wstring message{ L"Unhandled winrt exception encountered\n" }; + message.append(ex.message().c_str()); + + spdlog::error(message.c_str()); + + ShowMessageBoxError(message.c_str()); + } + catch (...) + { + auto lastErrorMessage = get_last_error_message(GetLastError()); + std::wstring message{ L"Unknown exception encountered\n" }; + message.append(lastErrorMessage ? std::move(*lastErrorMessage) : L""); + + spdlog::error(message.c_str()); + + ShowMessageBoxError(message.c_str()); + } + return 0; } diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj index 1da5c3c2b584..9c62fc947d38 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 @@ -88,7 +90,7 @@ true true true - WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;%(AdditionalDependencies) + WindowsApp.lib;Msi.lib;Shlwapi.lib;Comctl32.lib;Version.lib;%(AdditionalDependencies) @@ -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 80934f7d2186..d305b419170b 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 1270da086a6c..78ee2a5412ab 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/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp index d7d82d2122ae..bf0e61835ccb 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/src/ActionRunner/actionRunner.cpp b/src/ActionRunner/actionRunner.cpp index d388db4ff78b..28381ee929b8 100644 --- a/src/ActionRunner/actionRunner.cpp +++ b/src/ActionRunner/actionRunner.cpp @@ -24,7 +24,7 @@ #include #include "../runner/tray_icon.h" -#include "../runner/action_runner_utils.h" +#include "../runner/ActionRunnerUtils.h" using namespace cmdArg; diff --git a/src/Update/PowerToys.Update.cpp b/src/Update/PowerToys.Update.cpp index 87ed480fc2c6..13c7a11b5cf1 100644 --- a/src/Update/PowerToys.Update.cpp +++ b/src/Update/PowerToys.Update.cpp @@ -14,10 +14,9 @@ #include #include #include -#include -#include #include +#include #include #include #include @@ -33,8 +32,6 @@ #include "../runner/tray_icon.h" #include "../runner/UpdateUtils.h" -auto Strings = create_notifications_strings(); - using namespace cmdArg; namespace fs = std::filesystem; @@ -59,7 +56,7 @@ std::optional ObtainInstallerPath() 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(); + 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()); diff --git a/src/common/updating/http_client.cpp b/src/common/updating/http_client.cpp index 951d841d8b96..637fb1221ad8 100644 --- a/src/common/updating/http_client.cpp +++ b/src/common/updating/http_client.cpp @@ -1,72 +1,6 @@ #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 396c61271b3d..000000000000 --- 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 403ea1022005..2bf694605d69 100644 --- a/src/common/updating/installer.cpp +++ b/src/common/updating/installer.cpp @@ -2,157 +2,22 @@ #include "installer.h" #include -// TODO: remove; do not depend on toasts -#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 auto uninstall_result = MsiInstallProductW(package_path.c_str(), L"REMOVE=ALL"); - return ERROR_SUCCESS == uninstall_result; - } - - 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; diff --git a/src/common/updating/installer.h b/src/common/updating/installer.h index 02cbdcf4ce1f..e3f4e9b320cd 100644 --- a/src/common/updating/installer.h +++ b/src/common/updating/installer.h @@ -4,17 +4,10 @@ #include #include -#include "notifications.h" #include namespace updating { - std::wstring get_msi_package_path(); - bool uninstall_msi_version(const std::wstring& package_path); - 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(); diff --git a/src/common/updating/notifications.cpp b/src/common/updating/notifications.cpp deleted file mode 100644 index 7a08a1031f7b..000000000000 --- 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 421a32d71649..000000000000 --- 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 a80017ed4d45..35883b8f73a5 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 1aac92d7127e..a5a15e47de8a 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 c9caaba5c46b..0e53af32698b 100644 --- a/src/common/updating/updating.vcxproj +++ b/src/common/updating/updating.vcxproj @@ -35,20 +35,14 @@ - - - - - - @@ -56,9 +50,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 640764eddaa0..d6e5b80e0582 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,16 +38,10 @@ 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 000000000000..86b201a5d1db --- /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 000000000000..1489685005ac --- /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/runner/UpdateUtils.cpp b/src/runner/UpdateUtils.cpp index a1f35eb94170..2231ef5cef8e 100644 --- a/src/runner/UpdateUtils.cpp +++ b/src/runner/UpdateUtils.cpp @@ -7,21 +7,67 @@ #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; + +std::wstring CurrentVersionToNextVersion(const new_version_download_info& info) +{ + auto result = VersionHelper{ VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION }.toWstring(); + result += L" -> "; + result += info.version.toWstring(); + return result; +} + +void ShowNewVersionAvailable(const new_version_download_info& info) +{ + remove_toasts_by_tag(UPDATING_PROCESS_TOAST_TAG); + + 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); + + 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) { @@ -48,9 +94,9 @@ bool IsMeteredConnection() } void ProcessNewVersionInfo(const github_version_info& version_info, - UpdateState& state, - const bool download_update, - const bool show_notifications) + UpdateState& state, + const bool download_update, + const bool show_notifications) { state.githubUpdateLastCheckedDate.emplace(timeutil::now()); if (std::holds_alternative(version_info)) @@ -81,7 +127,7 @@ void ProcessNewVersionInfo(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 @@ -98,7 +144,7 @@ void ProcessNewVersionInfo(const github_version_info& version_info, state.downloadedInstallerFilename = {}; if (show_notifications) { - notifications::show_open_settings_for_update(Strings); + ShowOpenSettingsForUpdate(); } } } @@ -125,7 +171,7 @@ void PeriodicUpdateWorker() 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; @@ -160,7 +206,7 @@ void CheckForUpdatesCallback() 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 diff --git a/src/runner/UpdateUtils.h b/src/runner/UpdateUtils.h index 688cf9e70f7e..8de3a546e198 100644 --- a/src/runner/UpdateUtils.h +++ b/src/runner/UpdateUtils.h @@ -3,7 +3,7 @@ #include void PeriodicUpdateWorker(); -void CheckForUpdatesSettingsCallback(); +void CheckForUpdatesCallback(); namespace cmdArg { diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 005a6f914dc7..68bf77526db3 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -45,8 +45,6 @@ #include #include -extern updating::notifications::strings Strings; - namespace { const wchar_t PT_URI_PROTOCOL_SCHEME[] = L"powertoys://"; diff --git a/src/runner/settings_window.cpp b/src/runner/settings_window.cpp index 1bef7af64600..839de4167bc5 100644 --- a/src/runner/settings_window.cpp +++ b/src/runner/settings_window.cpp @@ -84,7 +84,7 @@ std::optional dispatch_json_action_to_module(const json::JsonObjec } else if (action == L"check_for_updates") { - CheckForUpdatesSettingsCallback(); + CheckForUpdatesCallback(); } else if (action == L"request_update_state_date") { From 8d4cbd40f1ae72b7348cc81f60e8f99e0bcf7b31 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Mon, 31 May 2021 12:10:04 +0300 Subject: [PATCH 4/9] fixup: formatting --- .../bootstrapper/bootstrapper.cpp | 777 +++++++++--------- 1 file changed, 388 insertions(+), 389 deletions(-) diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index e4326c265a86..79f34f8da7ea 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -23,9 +23,9 @@ static bool g_Silent = false; namespace // Strings in this namespace should not be localized { - const wchar_t APPLICATION_ID[] = L"PowerToysInstaller"; - const char EXE_LOG_FILENAME[] = "powertoys-bootstrapper-exe-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; - const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; + const wchar_t APPLICATION_ID[] = L"PowerToysInstaller"; + const char EXE_LOG_FILENAME[] = "powertoys-bootstrapper-exe-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; + const char MSI_LOG_FILENAME[] = "powertoys-bootstrapper-msi-" STR(VERSION_MAJOR) "." STR(VERSION_MINOR) "." STR(VERSION_REVISION) ".log"; } #undef STR @@ -35,83 +35,83 @@ namespace fs = std::filesystem; std::optional ExtractEmbeddedInstaller(const fs::path extractPath) { - auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN"); - if (!executableRes) - { - return std::nullopt; - } - - auto installerPath = extractPath / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi"; - return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt; + auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN"); + if (!executableRes) + { + return std::nullopt; + } + + auto installerPath = extractPath / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi"; + return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt; } void SetupLogger(fs::path directory, const spdlog::level::level_enum severity) { - std::shared_ptr logger; - auto nullLogger = spdlog::null_logger_mt("null"); - try - { - if (severity != spdlog::level::off) + std::shared_ptr logger; + auto nullLogger = spdlog::null_logger_mt("null"); + try { - logger = spdlog::basic_logger_mt("file", (directory / EXE_LOG_FILENAME).wstring()); + if (severity != spdlog::level::off) + { + logger = spdlog::basic_logger_mt("file", (directory / EXE_LOG_FILENAME).wstring()); + + std::error_code _; + const DWORD msiSev = severity == spdlog::level::debug ? INSTALLLOGMODE_VERBOSE : INSTALLLOGMODE_ERROR; + const auto msiLogPath = directory / MSI_LOG_FILENAME; + MsiEnableLogW(msiSev, msiLogPath.c_str(), INSTALLLOGATTRIBUTES_APPEND); + } + else + { + logger = nullLogger; + } - std::error_code _; - const DWORD msiSev = severity == spdlog::level::debug ? INSTALLLOGMODE_VERBOSE : INSTALLLOGMODE_ERROR; - const auto msiLogPath = directory / MSI_LOG_FILENAME; - MsiEnableLogW(msiSev, msiLogPath.c_str(), INSTALLLOGATTRIBUTES_APPEND); + logger->set_pattern("[%L][%d-%m-%C-%T] %v"); + logger->set_level(severity); + spdlog::set_default_logger(std::move(logger)); + spdlog::set_level(severity); + spdlog::flush_every(std::chrono::seconds(5)); } - else + catch (...) { - logger = nullLogger; + spdlog::set_default_logger(nullLogger); } - - logger->set_pattern("[%L][%d-%m-%C-%T] %v"); - logger->set_level(severity); - spdlog::set_default_logger(std::move(logger)); - spdlog::set_level(severity); - spdlog::flush_every(std::chrono::seconds(5)); - } - catch (...) - { - spdlog::set_default_logger(nullLogger); - } } void CleanupSettingsFromOlderVersions() { - try - { - const auto logSettingsFile = fs::path{ PTSettingsHelper::get_root_save_folder_location() } / PTSettingsHelper::log_settings_filename; - if (fs::is_regular_file(logSettingsFile)) + try { - fs::remove(logSettingsFile); - spdlog::info("Removed old log settings file"); + const auto logSettingsFile = fs::path{ PTSettingsHelper::get_root_save_folder_location() } / PTSettingsHelper::log_settings_filename; + if (fs::is_regular_file(logSettingsFile)) + { + fs::remove(logSettingsFile); + spdlog::info("Removed old log settings file"); + } + else + { + spdlog::info("Old log settings file wasn't found"); + } } - else + catch (...) { - spdlog::info("Old log settings file wasn't found"); + spdlog::error("Failed to cleanup old log settings"); } - } - catch (...) - { - spdlog::error("Failed to cleanup old log settings"); - } } 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); - } + if (!g_Silent) + { + MessageBoxW(nullptr, + message, + GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), + MB_OK | MB_ICONERROR); + } } void ShowMessageBoxError(const UINT messageId) { - ShowMessageBoxError(GET_RESOURCE_STRING(messageId).c_str()); + ShowMessageBoxError(GET_RESOURCE_STRING(messageId).c_str()); } bool uninstall_msi_version(const std::wstring& package_path) @@ -122,55 +122,54 @@ bool uninstall_msi_version(const std::wstring& package_path) 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 }; -} + 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(); - char* programFilesDir = nullptr; - size_t size = 0; - std::string defaultInstallDir; + winrt::init_apartment(); + char* programFilesDir = nullptr; + size_t size = 0; + std::string defaultInstallDir; - if (!_dupenv_s(&programFilesDir, &size, "PROGRAMFILES")) - { - defaultInstallDir += programFilesDir; - defaultInstallDir += "\\PowerToys"; - } + if (!_dupenv_s(&programFilesDir, &size, "PROGRAMFILES")) + { + defaultInstallDir += programFilesDir; + defaultInstallDir += "\\PowerToys"; + } - cxxopts::Options options{ "PowerToysBootstrapper" }; + cxxopts::Options options{ "PowerToysBootstrapper" }; - // clang-format off + // clang-format off options.add_options() ("h,help", "Show help") ("no_full_ui", "Use reduced UI for MSI") @@ -182,334 +181,334 @@ int Bootstrapper(HINSTANCE hInstance) ("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; - bool showHelp = false; - try - { - cmdArgs = options.parse(__argc, const_cast(__argv)); - } - catch (...) - { - showHelp = true; - } - - showHelp = showHelp || cmdArgs["help"].as(); - if (showHelp) - { - std::ostringstream helpMsg; - helpMsg << options.help(); - MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION); - return 0; - } - - g_Silent = cmdArgs["silent"].as(); - const bool noFullUI = cmdArgs["no_full_ui"].as(); - const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].as(); - const bool noStartPT = cmdArgs["no_start_pt"].as(); - const bool startPT = cmdArgs["start_pt"].as(); - const auto logLevel = cmdArgs["log_level"].as(); - const auto logDirArg = cmdArgs["log_dir"].as(); - const auto installDirArg = cmdArgs["install_dir"].as(); - const bool extractMsiOnly = cmdArgs["extract_msi"].as(); - - std::wstring installFolderProp; - if (!installDirArg.empty()) - { - std::string installDir; - if (installDirArg.find(' ') != std::string::npos) - { - installDir = "\"" + installDirArg + "\""; + // clang-format on + + cxxopts::ParseResult cmdArgs; + bool showHelp = false; + try + { + cmdArgs = options.parse(__argc, const_cast(__argv)); } - else + catch (...) { - installDir = installDirArg; + showHelp = true; } - installFolderProp = std::wstring(installDir.length(), L' '); - std::copy(installDir.begin(), installDir.end(), installFolderProp.begin()); - installFolderProp = L"INSTALLFOLDER=" + installFolderProp; - } - - fs::path logDir = "."; - try - { - fs::path logDirArgPath = logDirArg; - if (fs::exists(logDirArgPath) && fs::is_directory(logDirArgPath)) + showHelp = showHelp || cmdArgs["help"].as(); + if (showHelp) { - logDir = logDirArgPath; + std::ostringstream helpMsg; + helpMsg << options.help(); + MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION); + return 0; } - } - catch (...) - { - } - spdlog::level::level_enum severity = spdlog::level::debug; - if (logLevel == "error") - { - severity = spdlog::level::err; - } + g_Silent = cmdArgs["silent"].as(); + const bool noFullUI = cmdArgs["no_full_ui"].as(); + const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].as(); + const bool noStartPT = cmdArgs["no_start_pt"].as(); + const bool startPT = cmdArgs["start_pt"].as(); + const auto logLevel = cmdArgs["log_level"].as(); + const auto logDirArg = cmdArgs["log_dir"].as(); + const auto installDirArg = cmdArgs["install_dir"].as(); + const bool extractMsiOnly = cmdArgs["extract_msi"].as(); + + std::wstring installFolderProp; + if (!installDirArg.empty()) + { + std::string installDir; + if (installDirArg.find(' ') != std::string::npos) + { + installDir = "\"" + installDirArg + "\""; + } + else + { + installDir = installDirArg; + } - SetupLogger(logDir, severity); - spdlog::debug("PowerToys Bootstrapper is launched\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, g_Silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extractMsiOnly); + installFolderProp = std::wstring(installDir.length(), L' '); + std::copy(installDir.begin(), installDir.end(), installFolderProp.begin()); + installFolderProp = L"INSTALLFOLDER=" + installFolderProp; + } - // If a user requested an MSI -> extract it and exit - if (extractMsiOnly) - { - if (const auto installerPath = ExtractEmbeddedInstaller(fs::current_path())) + fs::path logDir = "."; + try { - spdlog::debug("MSI installer extracted to {}", installerPath->string()); + fs::path logDirArgPath = logDirArg; + if (fs::exists(logDirArgPath) && fs::is_directory(logDirArgPath)) + { + logDir = logDirArgPath; + } } - else + catch (...) { - spdlog::error("MSI installer couldn't be extracted"); } - return 0; - } - - const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); - - // Do not support installing on Windows < 1903 - //if (updating::is_1809_or_older()) - { - 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 = get_installed_powertoys_version(); - if (installedVersion && *installedVersion >= myVersion) - { - spdlog::error(L"Detected a newer version {} vs {}", (*installedVersion).toWstring(), myVersion.toWstring()); - ShowMessageBoxError(IDS_NEWER_VERSION_ERROR); - return 0; - } - - // Setup MSI UI visibility and restart as elevated if required - if (!noFullUI) - { - MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr); - } - - if (g_Silent) - { - if (is_process_elevated()) + spdlog::level::level_enum severity = spdlog::level::debug; + if (logLevel == "error") { - MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr); + severity = spdlog::level::err; } - else + + SetupLogger(logDir, severity); + spdlog::debug("PowerToys Bootstrapper is launched\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, g_Silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extractMsiOnly); + + // If a user requested an MSI -> extract it and exit + if (extractMsiOnly) { - spdlog::debug("MSI doesn't support silent mode without elevation => restarting elevated"); - // MSI fails to run in silent mode due to a suppressed UAC w/o elevation, - // so we restart ourselves elevated with the same args - std::wstring params; - int nCmdArgs = 0; - LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs); - for (int i = 1; i < nCmdArgs; ++i) - { - if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos) + if (const auto installerPath = ExtractEmbeddedInstaller(fs::current_path())) { - params += L'"'; - params += argList[i]; - params += L'"'; + spdlog::debug("MSI installer extracted to {}", installerPath->string()); } else { - params += argList[i]; + spdlog::error("MSI installer couldn't be extracted"); } - if (i != nCmdArgs - 1) - { - params += L' '; - } - } + return 0; + } - const auto processHandle = run_elevated(argList[0], params.c_str()); - if (!processHandle) - { - spdlog::error("Couldn't restart elevated to enable silent mode! ({})", GetLastError()); + const VersionHelper myVersion(VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION); + + // Do not support installing on Windows < 1903 + //if (updating::is_1809_or_older()) + { + ShowMessageBoxError(IDS_OLD_WINDOWS_ERROR); + spdlog::error("PowerToys {} requires at least Windows 1903 to run.", myVersion.toString()); return 1; - } - - if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0) - { - DWORD exitCode = 0; - GetExitCodeProcess(processHandle, &exitCode); - return exitCode; - } - else - { - spdlog::error("Elevated setup process timed out after 60m => using basic MSI UI ({})", GetLastError()); - // Couldn't install using the completely silent mode in an hour, use basic UI. - TerminateProcess(processHandle, 0); - MsiSetInternalUI(INSTALLUILEVEL_BASIC, nullptr); - } - } - } - - // Try killing PowerToys and prevent future processes launch by acquiring app mutex - for (auto& handle : getProcessHandlesByName(L"PowerToys.exe", PROCESS_TERMINATE)) - { - TerminateProcess(handle.get(), 0); - } - - auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME); - auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME); - if (!instanceMutex) - { - spdlog::error("Couldn't acquire PowerToys global mutex. Setup couldn't terminate PowerToys.exe process"); - return 1; - } - - spdlog::debug("Extracting embedded MSI installer"); - const auto installerPath = ExtractEmbeddedInstaller(fs::temp_directory_path()); - if (!installerPath) - { - ShowMessageBoxError(IDS_INSTALLER_EXTRACT_ERROR); - spdlog::error("Couldn't install the MSI installer ({})", GetLastError()); - return 1; - } - - auto removeExtractedInstaller = wil::scope_exit([&] { - std::error_code _; - fs::remove(*installerPath, _); - }); + } + + // Check if there's a newer version installed + const auto installedVersion = get_installed_powertoys_version(); + if (installedVersion && *installedVersion >= myVersion) + { + spdlog::error(L"Detected a newer version {} vs {}", (*installedVersion).toWstring(), myVersion.toWstring()); + ShowMessageBoxError(IDS_NEWER_VERSION_ERROR); + return 0; + } - spdlog::debug("Acquiring existing MSI package path if exists"); - const auto package_path = GetMsiPackagePath(); - if (!package_path.empty()) - { - spdlog::debug(L"Existing MSI package path found: {}", package_path); - } - else - { - spdlog::debug("Existing MSI package path not found"); - } - - 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); - return 1; - } - - const bool installDotnet = !skipDotnetInstall; - if (!g_Silent) - { - OpenProgressBarDialog(hInstance, 0, GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), GET_RESOURCE_STRING(IDS_DOWNLOADING_DOTNET).c_str()); - } - - try - { - if (installDotnet) - { - spdlog::debug("Detecting if dotnet is installed"); - const bool dotnetInstalled = updating::dotnet_is_installed(); - spdlog::debug("Dotnet is already installed: {}", dotnetInstalled); - if (!dotnetInstalled) - { - bool installedSuccessfully = false; - if (const auto dotnet_installer_path = updating::download_dotnet()) + // Setup MSI UI visibility and restart as elevated if required + if (!noFullUI) + { + MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr); + } + + if (g_Silent) + { + if (is_process_elevated()) { - // Dotnet installer has its own progress bar - CloseProgressBarDialog(); - installedSuccessfully = updating::install_dotnet(*dotnet_installer_path, g_Silent); - if (!installedSuccessfully) - { - spdlog::error("Couldn't install dotnet"); - } + MsiSetInternalUI(INSTALLUILEVEL_NONE, nullptr); } else { - spdlog::error("Couldn't download dotnet"); + spdlog::debug("MSI doesn't support silent mode without elevation => restarting elevated"); + // MSI fails to run in silent mode due to a suppressed UAC w/o elevation, + // so we restart ourselves elevated with the same args + std::wstring params; + int nCmdArgs = 0; + LPWSTR* argList = CommandLineToArgvW(GetCommandLineW(), &nCmdArgs); + for (int i = 1; i < nCmdArgs; ++i) + { + if (std::wstring_view{ argList[i] }.find(L' ') != std::wstring_view::npos) + { + params += L'"'; + params += argList[i]; + params += L'"'; + } + else + { + params += argList[i]; + } + + if (i != nCmdArgs - 1) + { + params += L' '; + } + } + + const auto processHandle = run_elevated(argList[0], params.c_str()); + if (!processHandle) + { + spdlog::error("Couldn't restart elevated to enable silent mode! ({})", GetLastError()); + return 1; + } + + if (WaitForSingleObject(processHandle, 3600000) == WAIT_OBJECT_0) + { + DWORD exitCode = 0; + GetExitCodeProcess(processHandle, &exitCode); + return exitCode; + } + else + { + spdlog::error("Elevated setup process timed out after 60m => using basic MSI UI ({})", GetLastError()); + // Couldn't install using the completely silent mode in an hour, use basic UI. + TerminateProcess(processHandle, 0); + MsiSetInternalUI(INSTALLUILEVEL_BASIC, nullptr); + } } + } + + // Try killing PowerToys and prevent future processes launch by acquiring app mutex + for (auto& handle : getProcessHandlesByName(L"PowerToys.exe", PROCESS_TERMINATE)) + { + TerminateProcess(handle.get(), 0); + } + + auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME); + auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME); + if (!instanceMutex) + { + spdlog::error("Couldn't acquire PowerToys global mutex. Setup couldn't terminate PowerToys.exe process"); + return 1; + } + + spdlog::debug("Extracting embedded MSI installer"); + const auto installerPath = ExtractEmbeddedInstaller(fs::temp_directory_path()); + if (!installerPath) + { + ShowMessageBoxError(IDS_INSTALLER_EXTRACT_ERROR); + spdlog::error("Couldn't install the MSI installer ({})", GetLastError()); + return 1; + } - if (!installedSuccessfully) + auto removeExtractedInstaller = wil::scope_exit([&] { + std::error_code _; + fs::remove(*installerPath, _); + }); + + spdlog::debug("Acquiring existing MSI package path if exists"); + const auto package_path = GetMsiPackagePath(); + if (!package_path.empty()) + { + spdlog::debug(L"Existing MSI package path found: {}", package_path); + } + else + { + spdlog::debug("Existing MSI package path not found"); + } + + 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); + return 1; + } + + const bool installDotnet = !skipDotnetInstall; + if (!g_Silent) + { + OpenProgressBarDialog(hInstance, 0, GET_RESOURCE_STRING(IDS_BOOTSTRAPPER_PROGRESS_TITLE).c_str(), GET_RESOURCE_STRING(IDS_DOWNLOADING_DOTNET).c_str()); + } + + try + { + if (installDotnet) { - ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR); + spdlog::debug("Detecting if dotnet is installed"); + const bool dotnetInstalled = updating::dotnet_is_installed(); + spdlog::debug("Dotnet is already installed: {}", dotnetInstalled); + if (!dotnetInstalled) + { + bool installedSuccessfully = false; + if (const auto dotnet_installer_path = updating::download_dotnet()) + { + // Dotnet installer has its own progress bar + CloseProgressBarDialog(); + installedSuccessfully = updating::install_dotnet(*dotnet_installer_path, g_Silent); + if (!installedSuccessfully) + { + spdlog::error("Couldn't install dotnet"); + } + } + else + { + spdlog::error("Couldn't download dotnet"); + } + + if (!installedSuccessfully) + { + ShowMessageBoxError(IDS_DOTNET_INSTALL_ERROR); + } + } } - } - } - } - catch (...) - { - 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(); - - const std::wstring msiProps = installFolderProp; - spdlog::debug("Launching MSI installation for new package {}", installerPath->string()); - const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS; - if (!installationDone) - { - spdlog::error("Couldn't install new MSI package ({})", GetLastError()); - return 1; - } - - spdlog::debug("Installation completed"); - - if ((!noStartPT && !g_Silent) || startPT) - { - spdlog::debug("Starting the newly installed PowerToys.exe"); - auto newPTPath = GetMsiPackageInstalledPath(); - if (!newPTPath) - { - spdlog::error("Couldn't determine new MSI package install location ({})", GetLastError()); - return 1; - } - - *newPTPath += L"\\PowerToys.exe"; - SHELLEXECUTEINFOW sei{ sizeof(sei) }; - sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE }; - sei.lpFile = newPTPath->c_str(); - sei.nShow = SW_SHOWNORMAL; - ShellExecuteExW(&sei); - } - - return 0; + } + catch (...) + { + 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(); + + const std::wstring msiProps = installFolderProp; + spdlog::debug("Launching MSI installation for new package {}", installerPath->string()); + const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS; + if (!installationDone) + { + spdlog::error("Couldn't install new MSI package ({})", GetLastError()); + return 1; + } + + spdlog::debug("Installation completed"); + + if ((!noStartPT && !g_Silent) || startPT) + { + spdlog::debug("Starting the newly installed PowerToys.exe"); + auto newPTPath = GetMsiPackageInstalledPath(); + if (!newPTPath) + { + spdlog::error("Couldn't determine new MSI package install location ({})", GetLastError()); + return 1; + } + + *newPTPath += L"\\PowerToys.exe"; + SHELLEXECUTEINFOW sei{ sizeof(sei) }; + sei.fMask = { SEE_MASK_FLAG_NO_UI | SEE_MASK_NOASYNC | SEE_MASK_NO_CONSOLE }; + sei.lpFile = newPTPath->c_str(); + sei.nShow = SW_SHOWNORMAL; + ShellExecuteExW(&sei); + } + + return 0; } int WINAPI WinMain(HINSTANCE hi, HINSTANCE, LPSTR, int) { - try - { - return Bootstrapper(hi); - } - catch (const std::exception& ex) - { - std::string messageA{ "Unhandled std exception encountered\n" }; - messageA.append(ex.what()); - - spdlog::error(messageA.c_str()); - - std::wstring messageW{}; - std::copy(messageA.begin(), messageA.end(), messageW.begin()); - ShowMessageBoxError(messageW.c_str()); - } - catch (winrt::hresult_error const& ex) - { - std::wstring message{ L"Unhandled winrt exception encountered\n" }; - message.append(ex.message().c_str()); - - spdlog::error(message.c_str()); - - ShowMessageBoxError(message.c_str()); - } - catch (...) - { - auto lastErrorMessage = get_last_error_message(GetLastError()); - std::wstring message{ L"Unknown exception encountered\n" }; - message.append(lastErrorMessage ? std::move(*lastErrorMessage) : L""); - - spdlog::error(message.c_str()); - - ShowMessageBoxError(message.c_str()); - } - return 0; + try + { + return Bootstrapper(hi); + } + catch (const std::exception& ex) + { + std::string messageA{ "Unhandled std exception encountered\n" }; + messageA.append(ex.what()); + + spdlog::error(messageA.c_str()); + + std::wstring messageW{}; + std::copy(messageA.begin(), messageA.end(), messageW.begin()); + ShowMessageBoxError(messageW.c_str()); + } + catch (winrt::hresult_error const& ex) + { + std::wstring message{ L"Unhandled winrt exception encountered\n" }; + message.append(ex.message().c_str()); + + spdlog::error(message.c_str()); + + ShowMessageBoxError(message.c_str()); + } + catch (...) + { + auto lastErrorMessage = get_last_error_message(GetLastError()); + std::wstring message{ L"Unknown exception encountered\n" }; + message.append(lastErrorMessage ? std::move(*lastErrorMessage) : L""); + + spdlog::error(message.c_str()); + + ShowMessageBoxError(message.c_str()); + } + return 0; } From 61a1bfeb9296841c4364015a7711d285a8123336 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Tue, 1 Jun 2021 12:19:02 +0300 Subject: [PATCH 5/9] fixup: review fixes --- installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp index 79f34f8da7ea..4420fed78d9c 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -271,7 +272,7 @@ 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()); From ecb2069d7f0dfe3295c94b6f6f4ea8c32b27e401 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Tue, 1 Jun 2021 16:31:48 +0300 Subject: [PATCH 6/9] fixup: review comments --- src/common/updating/http_client.cpp | 6 ------ src/common/updating/installer.cpp | 5 ----- src/common/updating/installer.h | 2 -- 3 files changed, 13 deletions(-) delete mode 100644 src/common/updating/http_client.cpp diff --git a/src/common/updating/http_client.cpp b/src/common/updating/http_client.cpp deleted file mode 100644 index 637fb1221ad8..000000000000 --- a/src/common/updating/http_client.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "pch.h" -#include "http_client.h" - -namespace http -{ -} \ No newline at end of file diff --git a/src/common/updating/installer.cpp b/src/common/updating/installer.cpp index 2bf694605d69..2be4a97c5f07 100644 --- a/src/common/updating/installer.cpp +++ b/src/common/updating/installer.cpp @@ -43,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 e3f4e9b320cd..5f2ca4bbb984 100644 --- a/src/common/updating/installer.h +++ b/src/common/updating/installer.h @@ -9,6 +9,4 @@ namespace updating { std::future uninstall_previous_msix_version_async(); - - bool is_1809_or_older(); } \ No newline at end of file From 6e5d1b893c3d8623105910c0662812b2ad009a29 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Wed, 9 Jun 2021 18:06:55 +0300 Subject: [PATCH 7/9] [Installer] Remove Winstore, redundant strings --- PowerToys.sln | 25 +++---- .../bootstrapper/Resources.resx | 21 ------ .../bootstrapper/bootstrapper.vcxproj | 4 +- src/ActionRunner/Resources.resx | 21 ------ src/Update/Resources.resx | 9 --- src/common/WinStore/Winstore.vcxproj | 54 -------------- src/common/WinStore/packages.config | 4 -- src/common/WinStore/winstore.cpp | 70 ------------------ src/common/WinStore/winstore.h | 16 ----- src/common/notifications/notifications.cpp | 48 ++----------- src/common/notifications/notifications.h | 1 - .../notifications/notifications.vcxproj | 5 -- src/common/updating/updating.vcxproj | 1 - src/runner/Resources.resx | 9 --- src/runner/general_settings.cpp | 72 ++++++------------- src/runner/main.cpp | 9 --- src/runner/runner.vcxproj | 3 - 17 files changed, 36 insertions(+), 336 deletions(-) delete mode 100644 src/common/WinStore/Winstore.vcxproj delete mode 100644 src/common/WinStore/packages.config delete mode 100644 src/common/WinStore/winstore.cpp delete mode 100644 src/common/WinStore/winstore.h diff --git a/PowerToys.sln b/PowerToys.sln index 029a0fca3ea5..6ccb0cab0921 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}" @@ -627,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 @@ -683,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 @@ -797,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} @@ -814,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/bootstrapper/Resources.resx b/installer/PowerToysBootstrapper/bootstrapper/Resources.resx index ce29162af4c3..85368cc4679c 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.vcxproj b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj index 9c62fc947d38..0b034d3e6379 100644 --- a/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj +++ b/installer/PowerToysBootstrapper/bootstrapper/bootstrapper.vcxproj @@ -73,7 +73,7 @@ - Level4 + Level3 true true true @@ -95,7 +95,7 @@ - Level4 + Level3 true _DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDebug diff --git a/src/ActionRunner/Resources.resx b/src/ActionRunner/Resources.resx index 7e2feb1971a8..443b7b0f47f5 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/Update/Resources.resx b/src/Update/Resources.resx index 7e2feb1971a8..a141dacd3da5 100644 --- a/src/Update/Resources.resx +++ b/src/Update/Resources.resx @@ -70,9 +70,6 @@ Update now - - Error: please uninstall the previous version of PowerToys manually. - An update to PowerToys is available. Visit our GitHub page to update. @@ -82,10 +79,4 @@ PowerToys Update - - We've detected a previous installation of PowerToys. Would you like to remove it? - - - PowerToys: uninstall previous version? - diff --git a/src/common/WinStore/Winstore.vcxproj b/src/common/WinStore/Winstore.vcxproj deleted file mode 100644 index bbefd414e43b..000000000000 --- 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/packages.config b/src/common/WinStore/packages.config deleted file mode 100644 index 81f107b8bcab..000000000000 --- a/src/common/WinStore/packages.config +++ /dev/null @@ -1,4 +0,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 270bd61d44ac..000000000000 --- 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 514bfeef079d..000000000000 --- 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/notifications/notifications.cpp b/src/common/notifications/notifications.cpp index ed10ec4ebe8c..4d58bcbb38d3 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 4e4ea6fd9e56..4f4247f15907 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 2d2e4d652209..b76d42a3bfa0 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/updating.vcxproj b/src/common/updating/updating.vcxproj index 0e53af32698b..7d060e588c57 100644 --- a/src/common/updating/updating.vcxproj +++ b/src/common/updating/updating.vcxproj @@ -39,7 +39,6 @@ - diff --git a/src/runner/Resources.resx b/src/runner/Resources.resx index 801a308b3fea..8656bfff10c0 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/general_settings.cpp b/src/runner/general_settings.cpp index d46398fa793c..ecc40c564fd7 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 @@ -65,7 +64,7 @@ GeneralSettings get_general_settings() { const bool is_user_admin = check_user_is_admin(); GeneralSettings settings{ - .isPackaged = winstore::running_as_packaged(), + .isPackaged = false, .isElevated = is_process_elevated(), .isRunElevated = run_as_elevated, .isAdmin = is_user_admin, @@ -75,31 +74,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,39 +93,32 @@ 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()) - { - winstore::switch_startup_task_state_async(startup).wait(); - } - else + if (startup) { - 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(general_configs.GetNamedBoolean(L"run_elevated", false)); + create_auto_start_task_for_this_user(false); + + run_as_elevated = false; } - else + else if (!general_configs.GetNamedBoolean(L"run_elevated", false)) { - 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(false); } } - else - { - delete_auto_start_task_for_this_user(); - } + } + else + { + delete_auto_start_task_for_this_user(); } } if (json::has(general_configs, L"enabled")) diff --git a/src/runner/main.cpp b/src/runner/main.cpp index 68bf77526db3..73281c826755 100644 --- a/src/runner/main.cpp +++ b/src/runner/main.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include "UpdateUtils.h" #include "ActionRunnerUtils.h" @@ -128,8 +127,6 @@ int runner(bool isProcessElevated, bool openSettings, bool openOobe) } } }.detach(); - notifications::register_background_toast_handler(); - chdir_current_executable(); // Load Powertoys DLLs @@ -265,12 +262,6 @@ toast_notification_handler_result toast_notification_handler(const std::wstring_ } } -// TODO: dummy function to be removed to avoid conflicts with https://github.com/microsoft/PowerToys/pull/11450 -bool start_msi_uninstallation_sequence() -{ - return true; -} - int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { winrt::init_apartment(); diff --git a/src/runner/runner.vcxproj b/src/runner/runner.vcxproj index cc786f8ef3d2..7c1253912844 100644 --- a/src/runner/runner.vcxproj +++ b/src/runner/runner.vcxproj @@ -110,9 +110,6 @@ {17da04df-e393-4397-9cf0-84dabe11032e} - - {c502a854-53ac-4ebb-8dc0-e4af2191e4f6} - From f62966f8f0f764c29eeb4df14c1ac323a107ae24 Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Thu, 10 Jun 2021 17:46:08 +0300 Subject: [PATCH 8/9] [Settings] Remove deprecated 'packaged' setting --- src/runner/general_settings.cpp | 2 -- src/runner/general_settings.h | 1 - .../GeneralSettings.cs | 5 ----- .../ViewModels/GeneralViewModel.cs | 19 ------------------- .../ViewModelTests/General.cs | 1 - 5 files changed, 28 deletions(-) diff --git a/src/runner/general_settings.cpp b/src/runner/general_settings.cpp index ecc40c564fd7..e4faf98dca60 100644 --- a/src/runner/general_settings.cpp +++ b/src/runner/general_settings.cpp @@ -21,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()) { @@ -64,7 +63,6 @@ GeneralSettings get_general_settings() { const bool is_user_admin = check_user_is_admin(); GeneralSettings settings{ - .isPackaged = false, .isElevated = is_process_elevated(), .isRunElevated = run_as_elevated, .isAdmin = is_user_admin, diff --git a/src/runner/general_settings.h b/src/runner/general_settings.h index f0b51733c6cf..5cbe1fefab67 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/settings-ui/Microsoft.PowerToys.Settings.UI.Library/GeneralSettings.cs b/src/settings-ui/Microsoft.PowerToys.Settings.UI.Library/GeneralSettings.cs index 9c062e9bd4d8..0c43a3cffb88 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 @@ public class GeneralSettings : ISettingsConfig [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 bbe68746c4b3..a89b46e6d71d 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 @@ public GeneralViewModel(ISettingsRepository settingsRepository, } } - private bool _packaged; private bool _startup; private bool _isElevated; private bool _runElevated; @@ -130,24 +129,6 @@ public GeneralViewModel(ISettingsRepository settingsRepository, 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 8aef0f8e1061..9293f222ffc8 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 @@ public void OriginalFilesModificationTest(string version) // 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); From 24131e816892e783b621ba501896e6622b1ac19c Mon Sep 17 00:00:00 2001 From: yuyoyuppe Date: Thu, 10 Jun 2021 19:51:51 +0300 Subject: [PATCH 9/9] fixup: fix build --- .../PowerToysSetupCustomActions.vcxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj index dde59dc0f850..226a800022ca 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)