bootstrapper: add --extract_msi arg for users that must access MSI (#8646)

* bootstrapper: add --extract_msi arg for users that must access MSI

- clean up setting outdated MSI properties
- minor fixes
This commit is contained in:
Andrey Nekrasov 2020-12-17 19:58:15 +03:00 committed by GitHub
parent e58ff6c71c
commit 0709b0648a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 14 deletions

View File

@ -17,7 +17,6 @@
#include "progressbar_window.h"
auto Strings = create_notifications_strings();
#define STR_HELPER(x) #x
@ -37,14 +36,14 @@ namespace // Strings in this namespace should not be localized
namespace fs = std::filesystem;
std::optional<fs::path> extractEmbeddedInstaller()
std::optional<fs::path> extractEmbeddedInstaller(const fs::path extractPath)
{
auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN");
if (!executableRes)
{
return std::nullopt;
}
auto installerPath = fs::temp_directory_path() / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi";
auto installerPath = extractPath / L"PowerToysBootstrappedInstaller-" PRODUCT_VERSION_STRING L".msi";
return executableRes->saveAsFile(installerPath) ? std::make_optional(std::move(installerPath)) : std::nullopt;
}
@ -106,7 +105,8 @@ int bootstrapper(HINSTANCE hInstance)
("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<std::string>()->default_value("off"))
("log_dir", "Log directory", cxxopts::value<std::string>()->default_value("."))
("install_dir", "Installation directory", cxxopts::value<std::string>()->default_value(defaultInstallDir));
("install_dir", "Installation directory", cxxopts::value<std::string>()->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;
@ -127,6 +127,7 @@ int bootstrapper(HINSTANCE hInstance)
MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION);
return 0;
}
const bool noFullUI = cmdArgs["no_full_ui"].as<bool>();
const bool silent = cmdArgs["silent"].as<bool>();
const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].as<bool>();
@ -134,6 +135,8 @@ int bootstrapper(HINSTANCE hInstance)
const auto logLevel = cmdArgs["log_level"].as<std::string>();
const auto logDirArg = cmdArgs["log_dir"].as<std::string>();
const auto installDirArg = cmdArgs["install_dir"].as<std::string>();
const bool extract_msi_only = cmdArgs["extract_msi"].as<bool>();
spdlog::level::level_enum severity = spdlog::level::off;
std::wstring installFolderProp;
@ -176,8 +179,23 @@ int bootstrapper(HINSTANCE hInstance)
severity = spdlog::level::err;
}
setup_log(logDir, severity);
spdlog::debug("PowerToys Bootstrapper is launched!\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}", noFullUI, silent, noStartPT, skipDotnetInstall, logLevel, installDirArg);
spdlog::debug("PowerToys Bootstrapper is launched!\nnoFullUI: {}\nsilent: {}\nno_start_pt: {}\nskip_dotnet_install: {}\nlog_level: {}\ninstall_dir: {}\nextract_msi: {}\n", noFullUI, silent, noStartPT, skipDotnetInstall, logLevel, installDirArg, extract_msi_only);
// If a user requested an MSI -> extract it and exit
if (extract_msi_only)
{
if (const auto installerPath = extractEmbeddedInstaller(fs::current_path()))
{
spdlog::info("MSI installer was extracted to {}", installerPath->string());
}
else
{
spdlog::error("MSI installer couldn't be extracted");
}
return 0;
}
// Setup MSI UI visibility and restart as elevated if required
if (!noFullUI)
{
MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr);
@ -236,13 +254,12 @@ int bootstrapper(HINSTANCE hInstance)
}
}
// Try killing PowerToys and prevent future processes launch
// 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)
{
@ -264,7 +281,7 @@ int bootstrapper(HINSTANCE hInstance)
}
spdlog::debug("Extracting embedded MSI installer");
const auto installerPath = extractEmbeddedInstaller();
const auto installerPath = extractEmbeddedInstaller(fs::temp_directory_path());
if (!installerPath)
{
if (!silent)
@ -309,7 +326,7 @@ int bootstrapper(HINSTANCE hInstance)
{
spdlog::debug("Detecting if dotnet is installed");
const bool dotnetInstalled = updating::dotnet_is_installed();
spdlog::debug("Dotnet is installed: {}", dotnetInstalled);
spdlog::debug("Dotnet is already installed: {}", dotnetInstalled);
if (!dotnetInstalled)
{
bool installed_successfully = false;
@ -347,8 +364,7 @@ int bootstrapper(HINSTANCE hInstance)
// At this point, there's no reason to show progress bar window, since MSI installers have their own
close_progressbar_window();
// Always skip dotnet install, because we should've installed it from here earlier
std::wstring msiProps = L"SKIPDOTNETINSTALL=1 " + installFolderProp;
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)

View File

@ -70,7 +70,6 @@
<Property Id="INSTALLSTARTMENUSHORTCUT" Value="1"/>
<Property Id="CREATESCHEDULEDTASK" Value="1"/>
<Property Id="WixShellExecTarget" Value="[#action_runner.exe]" />
<Property Id="SKIPDOTNETINSTALL" Value="0"/>
<Property Id ="EXISTINGPOWERRENAMEEXTPATH">
<RegistrySearch Id="ExistingExtPath" Root="HKCR" Key="CLSID\{0440049F-D1DC-4E46-B27B-98393D79486B}\InprocServer32" Type="raw"/>

View File

@ -173,7 +173,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
}
std::wstring_view action{ args[1] };
if (action == L"-run-non-elevated")
if (action == RUN_NONELEVATED_CMDARG)
{
int nextArg = 2;
@ -235,7 +235,7 @@ int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
}
}
}
else if (action == L"-uninstall_msi")
else if (action == UNINSTALL_MSI_CMDARG)
{
return uninstall_msi_action();
}

View File

@ -12,4 +12,8 @@ const inline wchar_t* UPDATE_NOW_LAUNCH_STAGE2_CMDARG = L"-update_now_stage_2";
const inline wchar_t* UPDATE_STAGE2_RESTART_PT_CMDARG = L"restart";
const inline wchar_t* UPDATE_STAGE2_DONT_START_PT_CMDARG = L"dont_start";
const inline wchar_t * UNINSTALL_MSI_CMDARG = L"-uninstall_msi";
const inline wchar_t * RUN_NONELEVATED_CMDARG = L"-run-non-elevated";
const inline wchar_t* UPDATE_REPORT_SUCCESS = L"-report_update_success";