mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-06-07 09:28:03 +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"
|
#include "progressbar_window.h"
|
||||||
|
|
||||||
|
|
||||||
auto Strings = create_notifications_strings();
|
auto Strings = create_notifications_strings();
|
||||||
|
|
||||||
#define STR_HELPER(x) #x
|
#define STR_HELPER(x) #x
|
||||||
@ -37,14 +36,14 @@ namespace // Strings in this namespace should not be localized
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
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");
|
auto executableRes = RcResource::create(IDR_BIN_MSIINSTALLER, L"BIN");
|
||||||
if (!executableRes)
|
if (!executableRes)
|
||||||
{
|
{
|
||||||
return std::nullopt;
|
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;
|
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")
|
("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_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("."))
|
("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
|
// clang-format on
|
||||||
cxxopts::ParseResult cmdArgs;
|
cxxopts::ParseResult cmdArgs;
|
||||||
bool showHelp = false;
|
bool showHelp = false;
|
||||||
@ -127,6 +127,7 @@ int bootstrapper(HINSTANCE hInstance)
|
|||||||
MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION);
|
MessageBoxA(nullptr, helpMsg.str().c_str(), "Help", MB_OK | MB_ICONINFORMATION);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool noFullUI = cmdArgs["no_full_ui"].as<bool>();
|
const bool noFullUI = cmdArgs["no_full_ui"].as<bool>();
|
||||||
const bool silent = cmdArgs["silent"].as<bool>();
|
const bool silent = cmdArgs["silent"].as<bool>();
|
||||||
const bool skipDotnetInstall = cmdArgs["skip_dotnet_install"].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 logLevel = cmdArgs["log_level"].as<std::string>();
|
||||||
const auto logDirArg = cmdArgs["log_dir"].as<std::string>();
|
const auto logDirArg = cmdArgs["log_dir"].as<std::string>();
|
||||||
const auto installDirArg = cmdArgs["install_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;
|
spdlog::level::level_enum severity = spdlog::level::off;
|
||||||
|
|
||||||
std::wstring installFolderProp;
|
std::wstring installFolderProp;
|
||||||
@ -176,8 +179,23 @@ int bootstrapper(HINSTANCE hInstance)
|
|||||||
severity = spdlog::level::err;
|
severity = spdlog::level::err;
|
||||||
}
|
}
|
||||||
setup_log(logDir, severity);
|
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)
|
if (!noFullUI)
|
||||||
{
|
{
|
||||||
MsiSetInternalUI(INSTALLUILEVEL_FULL, nullptr);
|
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))
|
for (auto& handle : getProcessHandlesByName(L"PowerToys.exe", PROCESS_TERMINATE))
|
||||||
{
|
{
|
||||||
TerminateProcess(handle.get(), 0);
|
TerminateProcess(handle.get(), 0);
|
||||||
}
|
}
|
||||||
auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME);
|
auto powerToysMutex = createAppMutex(POWERTOYS_MSI_MUTEX_NAME);
|
||||||
|
|
||||||
auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME);
|
auto instanceMutex = createAppMutex(POWERTOYS_BOOTSTRAPPER_MUTEX_NAME);
|
||||||
if (!instanceMutex)
|
if (!instanceMutex)
|
||||||
{
|
{
|
||||||
@ -264,7 +281,7 @@ int bootstrapper(HINSTANCE hInstance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
spdlog::debug("Extracting embedded MSI installer");
|
spdlog::debug("Extracting embedded MSI installer");
|
||||||
const auto installerPath = extractEmbeddedInstaller();
|
const auto installerPath = extractEmbeddedInstaller(fs::temp_directory_path());
|
||||||
if (!installerPath)
|
if (!installerPath)
|
||||||
{
|
{
|
||||||
if (!silent)
|
if (!silent)
|
||||||
@ -309,7 +326,7 @@ int bootstrapper(HINSTANCE hInstance)
|
|||||||
{
|
{
|
||||||
spdlog::debug("Detecting if dotnet is installed");
|
spdlog::debug("Detecting if dotnet is installed");
|
||||||
const bool dotnetInstalled = updating::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)
|
if (!dotnetInstalled)
|
||||||
{
|
{
|
||||||
bool installed_successfully = false;
|
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
|
// At this point, there's no reason to show progress bar window, since MSI installers have their own
|
||||||
close_progressbar_window();
|
close_progressbar_window();
|
||||||
|
|
||||||
// Always skip dotnet install, because we should've installed it from here earlier
|
const std::wstring msiProps = installFolderProp;
|
||||||
std::wstring msiProps = L"SKIPDOTNETINSTALL=1 " + installFolderProp;
|
|
||||||
spdlog::debug("Launching MSI installation for new package {}", installerPath->string());
|
spdlog::debug("Launching MSI installation for new package {}", installerPath->string());
|
||||||
const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS;
|
const bool installationDone = MsiInstallProductW(installerPath->c_str(), msiProps.c_str()) == ERROR_SUCCESS;
|
||||||
if (!installationDone)
|
if (!installationDone)
|
||||||
|
@ -70,7 +70,6 @@
|
|||||||
<Property Id="INSTALLSTARTMENUSHORTCUT" Value="1"/>
|
<Property Id="INSTALLSTARTMENUSHORTCUT" Value="1"/>
|
||||||
<Property Id="CREATESCHEDULEDTASK" Value="1"/>
|
<Property Id="CREATESCHEDULEDTASK" Value="1"/>
|
||||||
<Property Id="WixShellExecTarget" Value="[#action_runner.exe]" />
|
<Property Id="WixShellExecTarget" Value="[#action_runner.exe]" />
|
||||||
<Property Id="SKIPDOTNETINSTALL" Value="0"/>
|
|
||||||
|
|
||||||
<Property Id ="EXISTINGPOWERRENAMEEXTPATH">
|
<Property Id ="EXISTINGPOWERRENAMEEXTPATH">
|
||||||
<RegistrySearch Id="ExistingExtPath" Root="HKCR" Key="CLSID\{0440049F-D1DC-4E46-B27B-98393D79486B}\InprocServer32" Type="raw"/>
|
<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] };
|
std::wstring_view action{ args[1] };
|
||||||
|
|
||||||
if (action == L"-run-non-elevated")
|
if (action == RUN_NONELEVATED_CMDARG)
|
||||||
{
|
{
|
||||||
int nextArg = 2;
|
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();
|
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_RESTART_PT_CMDARG = L"restart";
|
||||||
const inline wchar_t* UPDATE_STAGE2_DONT_START_PT_CMDARG = L"dont_start";
|
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";
|
const inline wchar_t* UPDATE_REPORT_SUCCESS = L"-report_update_success";
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user