mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-01-18 22:43:31 +08:00
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:
parent
e58ff6c71c
commit
0709b0648a
@ -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)
|
||||
|
@ -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"/>
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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";
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user