Suppress MSI-initiated reboots during Store updates#40079
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR prevents Windows Installer from initiating automatic system reboots during Store-driven WSL MSIX updates by forcing MSI operations to use REBOOT=ReallySuppress, and adjusts handling of the “reboot required” success code (3010) across installer and CLI paths.
Changes:
- Append
REBOOT=ReallySuppressto MSI upgrade/install arguments inUpgradeViaMsi. - Switch MSI uninstall to
MsiConfigureProductEx(..., "REBOOT=ReallySuppress")so uninstall also suppresses MSI-initiated reboots. - Treat
ERROR_SUCCESS_REBOOT_REQUIRED(3010) as non-fatal in update/uninstall flows, with user-visible messaging in CLI paths and silent success behavior in the background service.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/windows/wslinstaller/exe/WslInstaller.cpp | Treats MSI 3010 as success for the silent background installer service. |
| src/windows/common/WslClient.cpp | Updates wsl --uninstall handling to print a reboot-required message on 3010 instead of treating it as failure. |
| src/windows/common/install.cpp | Ensures MSI upgrade/uninstall operations always suppress MSI-initiated reboot; prints reboot-required message on update when MSI returns 3010. |
Comments suppressed due to low confidence (2)
src/windows/common/WslClient.cpp:1294
- This path treats
ERROR_SUCCESS_REBOOT_REQUIRED(3010) as non-fatal, but still returnsexitCodeto the process. That will makewsl --uninstallexit with 3010 even though the uninstall succeeded, which is inconsistent with other commands that print the reboot-needed message but still return 0 (e.g., install prerequisites). If the intent is “success with reboot required”, consider returning 0 after printing while still surfacing the reboot requirement in output.
if (exitCode == ERROR_SUCCESS_REBOOT_REQUIRED)
{
wsl::windows::common::wslutil::PrintSystemError(ERROR_SUCCESS_REBOOT_REQUIRED);
}
else if (exitCode != 0)
{
clearLogs.release();
THROW_HR_WITH_USER_ERROR(
HRESULT_FROM_WIN32(exitCode),
wsl::shared::Localization::MessageUninstallFailed(exitCode) + L"\r\n" +
wsl::shared::Localization::MessageSeeLogFile(logFile.c_str()));
}
return exitCode;
}
src/windows/common/install.cpp:137
- PR description says
ERROR_SUCCESS_REBOOT_REQUIRED (3010)is “propagated to callers”, but this update path prints the reboot-needed message and then still returns 0 fromUpdatePackageImpl(). If the desired behavior is to propagate 3010 to thewsl --updateexit code (so callers can detect reboot-needed), this implementation doesn’t do that; otherwise, the PR description should be updated to reflect thatwsl --updatestill exits 0 on 3010.
const auto exitCode = UpgradeViaMsi(downloadPath.c_str(), L"", logFile.c_str(), &MsiMessageCallback);
if (exitCode == ERROR_SUCCESS_REBOOT_REQUIRED)
{
PrintSystemError(ERROR_SUCCESS_REBOOT_REQUIRED);
}
else if (exitCode != 0)
{
clearLogs.release();
THROW_HR_WITH_USER_ERROR(
HRESULT_FROM_WIN32(exitCode),
wsl::shared::Localization::MessageUpdateFailed(exitCode) + L"\r\n" +
wsl::shared::Localization::MessageSeeLogFile(logFile.c_str()));
}
}
else
{
// Set FILE_FLAG_DELETE_ON_CLOSE on the file to make sure it's deleted when the installation completes.
const wil::unique_hfile package{CreateFileW(
downloadPath.c_str(), DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, nullptr)};
THROW_LAST_ERROR_IF(!package);
const winrt::Windows::Management::Deployment::PackageManager packageManager;
const auto result = packageManager.AddPackageAsync(
Uri{downloadPath.c_str()}, nullptr, DeploymentOptions::ForceApplicationShutdown | DeploymentOptions::ForceTargetApplicationShutdown);
THROW_IF_FAILED(result.get().ExtendedErrorCode());
// Note: If the installation is successful, this process is expected to receive and Ctrl-C and exit
}
return 0;
When the WSL MSIX package is updated via the Microsoft Store, the WslInstaller service automatically upgrades the MSI package by calling MsiInstallProduct. This call was made with INSTALLUILEVEL_NONE (silent install) but without setting the REBOOT=ReallySuppress property. Per Windows Installer documentation, when a silent install encounters files in use and REBOOT is not suppressed, the system reboots automatically without any user prompt. This could cause unexpected machine restarts after a Store update when WSL binaries (e.g. wslservice.exe) were in use during the upgrade. Every deployment script in the repo already passes /norestart to msiexec (deploy-to-host.ps1, deploy-to-vm.ps1, install-latest-wsl.ps1, test-setup.ps1), but the programmatic MsiInstallProduct path used by the WslInstaller service lacked the equivalent property. This change: - Always appends REBOOT=ReallySuppress to MsiInstallProduct arguments in UpgradeViaMsi, preventing Windows Installer from ever initiating a system restart during install/upgrade. - Switches UninstallViaMsi from MsiConfigureProduct to MsiConfigureProductEx so we can pass REBOOT=ReallySuppress during uninstall as well. - Propagates ERROR_SUCCESS_REBOOT_REQUIRED (3010) to callers instead of swallowing it. User-facing paths (wsl --update, wsl --uninstall) print a reboot-needed message to stderr. The background WslInstaller service silently treats 3010 as success since it has no console. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
6fd02e3 to
da73f0e
Compare
OneBlue
approved these changes
Apr 6, 2026
benhillis
added a commit
that referenced
this pull request
Apr 7, 2026
When the WSL MSIX package is updated via the Microsoft Store, the WslInstaller service automatically upgrades the MSI package by calling MsiInstallProduct. This call was made with INSTALLUILEVEL_NONE (silent install) but without setting the REBOOT=ReallySuppress property. Per Windows Installer documentation, when a silent install encounters files in use and REBOOT is not suppressed, the system reboots automatically without any user prompt. This could cause unexpected machine restarts after a Store update when WSL binaries (e.g. wslservice.exe) were in use during the upgrade. Every deployment script in the repo already passes /norestart to msiexec (deploy-to-host.ps1, deploy-to-vm.ps1, install-latest-wsl.ps1, test-setup.ps1), but the programmatic MsiInstallProduct path used by the WslInstaller service lacked the equivalent property. This change: - Always appends REBOOT=ReallySuppress to MsiInstallProduct arguments in UpgradeViaMsi, preventing Windows Installer from ever initiating a system restart during install/upgrade. - Switches UninstallViaMsi from MsiConfigureProduct to MsiConfigureProductEx so we can pass REBOOT=ReallySuppress during uninstall as well. - Propagates ERROR_SUCCESS_REBOOT_REQUIRED (3010) to callers instead of swallowing it. User-facing paths (wsl --update, wsl --uninstall) print a reboot-needed message to stderr. The background WslInstaller service silently treats 3010 as success since it has no console. Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cherry-pick of #40074 onto current master.
When the WSL MSIX package is updated via the Microsoft Store, the WslInstaller service automatically upgrades the MSI package by calling MsiInstallProduct. This call was made with INSTALLUILEVEL_NONE (silent install) but without setting the REBOOT=ReallySuppress property.
Per Windows Installer documentation, when a silent install encounters files in use and REBOOT is not suppressed, the system reboots automatically without any user prompt. This could cause unexpected machine restarts after a Store update when WSL binaries (e.g. wslservice.exe) were in use during the upgrade.
This change:
Fixes #14536