mirror of
https://github.com/microsoft/WSL.git
synced 2025-12-10 00:44:55 -06:00
Create a persistent install log file to help root cause package upgrade issues (#13500)
* Create a persistent install log file to help root cause package upgrade issues * Update src/windows/common/wslutil.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Collect log file in diagnostic script --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
parent
8313d50f2e
commit
e0c6196cd5
@ -56,6 +56,8 @@ if (Test-Path $wslconfig)
|
|||||||
Copy-Item $wslconfig $folder | Out-Null
|
Copy-Item $wslconfig $folder | Out-Null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Copy-Item "C:\Windows\temp\wsl-install-log.txt" $folder -ErrorAction ignore
|
||||||
|
|
||||||
get-appxpackage MicrosoftCorporationII.WindowsSubsystemforLinux -ErrorAction Ignore > $folder/appxpackage.txt
|
get-appxpackage MicrosoftCorporationII.WindowsSubsystemforLinux -ErrorAction Ignore > $folder/appxpackage.txt
|
||||||
get-acl "C:\ProgramData\Microsoft\Windows\WindowsApps" -ErrorAction Ignore | Format-List > $folder/acl.txt
|
get-acl "C:\ProgramData\Microsoft\Windows\WindowsApps" -ErrorAction Ignore | Format-List > $folder/acl.txt
|
||||||
Get-WindowsOptionalFeature -Online > $folder/optional-components.txt
|
Get-WindowsOptionalFeature -Online > $folder/optional-components.txt
|
||||||
|
|||||||
@ -397,6 +397,14 @@
|
|||||||
Execute="deferred"
|
Execute="deferred"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<CustomAction Id="FinalizeInstall"
|
||||||
|
Impersonate="no"
|
||||||
|
BinaryRef="wslinstall.dll"
|
||||||
|
DllEntry="WslFinalizeInstallation"
|
||||||
|
Return="check"
|
||||||
|
Execute="deferred"
|
||||||
|
/>
|
||||||
|
|
||||||
<CustomAction Id="DeprovisionMsix"
|
<CustomAction Id="DeprovisionMsix"
|
||||||
Impersonate="no"
|
Impersonate="no"
|
||||||
BinaryRef="wslinstall.dll"
|
BinaryRef="wslinstall.dll"
|
||||||
@ -533,6 +541,8 @@
|
|||||||
<Custom Action="CalculateWslSettingsProtocolIds" Before="WriteRegistryValues" Condition='(not REMOVE~="ALL")' />
|
<Custom Action="CalculateWslSettingsProtocolIds" Before="WriteRegistryValues" Condition='(not REMOVE~="ALL")' />
|
||||||
<?endif?>
|
<?endif?>
|
||||||
|
|
||||||
|
<Custom Action="FinalizeInstall" After="PublishFeatures"/>
|
||||||
|
|
||||||
</InstallExecuteSequence>
|
</InstallExecuteSequence>
|
||||||
|
|
||||||
<!-- Don't show a 'Modify' button in settings since there is nothing to modify -->
|
<!-- Don't show a 'Modify' button in settings since there is nothing to modify -->
|
||||||
|
|||||||
@ -135,6 +135,7 @@ static const std::map<HRESULT, LPCWSTR> g_commonErrors{
|
|||||||
X_WIN32(ERROR_INVALID_SECURITY_DESCR),
|
X_WIN32(ERROR_INVALID_SECURITY_DESCR),
|
||||||
X(VM_E_INVALID_STATE),
|
X(VM_E_INVALID_STATE),
|
||||||
X_WIN32(STATUS_SHUTDOWN_IN_PROGRESS),
|
X_WIN32(STATUS_SHUTDOWN_IN_PROGRESS),
|
||||||
|
X_WIN32(ERROR_BAD_PATHNAME),
|
||||||
X(WININET_E_TIMEOUT)};
|
X(WININET_E_TIMEOUT)};
|
||||||
|
|
||||||
#undef X
|
#undef X
|
||||||
@ -1344,10 +1345,17 @@ int WINAPI InstallRecordHandler(void* context, UINT messageType, LPCWSTR message
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
WSL_LOG("MSIMessage", TraceLoggingValue(messageType, "type"), TraceLoggingValue(message, "message"));
|
WSL_LOG("MSIMessage", TraceLoggingValue(messageType, "type"), TraceLoggingValue(message, "message"));
|
||||||
|
auto type = (INSTALLMESSAGE)(0xFF000000 & (UINT)messageType);
|
||||||
|
|
||||||
|
if (type == INSTALLMESSAGE_ERROR || type == INSTALLMESSAGE_FATALEXIT || type == INSTALLMESSAGE_WARNING)
|
||||||
|
{
|
||||||
|
WriteInstallLog(std::format("MSI message: {}", message));
|
||||||
|
}
|
||||||
|
|
||||||
auto* callback = reinterpret_cast<const std::function<void(UINT, LPCWSTR)>*>(context);
|
auto* callback = reinterpret_cast<const std::function<void(UINT, LPCWSTR)>*>(context);
|
||||||
if (callback != nullptr)
|
if (callback != nullptr)
|
||||||
{
|
{
|
||||||
(*callback)((INSTALLMESSAGE)(0xFF000000 & (UINT)messageType), message);
|
(*callback)(type, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CATCH_LOG();
|
CATCH_LOG();
|
||||||
@ -1401,6 +1409,8 @@ int wsl::windows::common::wslutil::UpdatePackage(bool PreRelease, bool Repair)
|
|||||||
UINT wsl::windows::common::wslutil::UpgradeViaMsi(
|
UINT wsl::windows::common::wslutil::UpgradeViaMsi(
|
||||||
_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
|
_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& Callback)
|
||||||
{
|
{
|
||||||
|
WriteInstallLog(std::format("Upgrading via MSI package: {}. Args: {}", PackageLocation, ExtraArgs != nullptr ? ExtraArgs : L""));
|
||||||
|
|
||||||
ConfigureMsiLogging(LogFile, Callback);
|
ConfigureMsiLogging(LogFile, Callback);
|
||||||
|
|
||||||
auto result = MsiInstallProduct(PackageLocation, ExtraArgs);
|
auto result = MsiInstallProduct(PackageLocation, ExtraArgs);
|
||||||
@ -1409,6 +1419,8 @@ UINT wsl::windows::common::wslutil::UpgradeViaMsi(
|
|||||||
TraceLoggingValue(result, "result"),
|
TraceLoggingValue(result, "result"),
|
||||||
TraceLoggingValue(ExtraArgs != nullptr ? ExtraArgs : L"", "ExtraArgs"));
|
TraceLoggingValue(ExtraArgs != nullptr ? ExtraArgs : L"", "ExtraArgs"));
|
||||||
|
|
||||||
|
WriteInstallLog(std::format("MSI upgrade result: {}", result));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1417,10 +1429,15 @@ UINT wsl::windows::common::wslutil::UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _I
|
|||||||
const auto key = OpenLxssMachineKey(KEY_READ);
|
const auto key = OpenLxssMachineKey(KEY_READ);
|
||||||
const auto productCode = ReadString(key.get(), L"Msi", L"ProductCode", nullptr);
|
const auto productCode = ReadString(key.get(), L"Msi", L"ProductCode", nullptr);
|
||||||
|
|
||||||
|
WriteInstallLog(std::format("Uninstalling MSI package: {}", productCode));
|
||||||
|
|
||||||
ConfigureMsiLogging(LogFile, Callback);
|
ConfigureMsiLogging(LogFile, Callback);
|
||||||
|
|
||||||
auto result = MsiConfigureProduct(productCode.c_str(), 0, INSTALLSTATE_ABSENT);
|
auto result = MsiConfigureProduct(productCode.c_str(), 0, INSTALLSTATE_ABSENT);
|
||||||
WSL_LOG("MsiUninstallResult", TraceLoggingValue(result, "result"));
|
WSL_LOG("MsiUninstallResult", TraceLoggingValue(result, "result"));
|
||||||
|
|
||||||
|
WriteInstallLog(std::format("MSI package uninstall result: {}", result));
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1451,6 +1468,43 @@ wil::unique_hfile wsl::windows::common::wslutil::ValidateFileSignature(LPCWSTR P
|
|||||||
return fileHandle;
|
return fileHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wsl::windows::common::wslutil::WriteInstallLog(const std::string& Content)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
static std::wstring path = wil::GetWindowsDirectoryW<std::wstring>() + L"\\temp\\wsl-install-log.txt";
|
||||||
|
|
||||||
|
// Wait up to 10 seconds for the log file mutex
|
||||||
|
wil::unique_handle mutex{CreateMutex(nullptr, true, L"Global\\WslInstallLog")};
|
||||||
|
THROW_LAST_ERROR_IF(!mutex);
|
||||||
|
|
||||||
|
THROW_LAST_ERROR_IF(WaitForSingleObject(mutex.get(), 10 * 1000) != WAIT_OBJECT_0);
|
||||||
|
|
||||||
|
wil::unique_handle file{CreateFile(
|
||||||
|
path.c_str(), GENERIC_ALL, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_ALWAYS, 0, nullptr)};
|
||||||
|
|
||||||
|
THROW_LAST_ERROR_IF(!file);
|
||||||
|
|
||||||
|
LARGE_INTEGER size{};
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(GetFileSizeEx(file.get(), &size));
|
||||||
|
|
||||||
|
// Append to the file if its size is below 10MB, otherwise truncate.
|
||||||
|
if (size.QuadPart < 10 * _1MB)
|
||||||
|
{
|
||||||
|
THROW_LAST_ERROR_IF(SetFilePointer(file.get(), 0, nullptr, FILE_END) == INVALID_SET_FILE_POINTER);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(SetEndOfFile(file.get()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static auto processName = wil::GetModuleFileNameW<std::wstring>();
|
||||||
|
auto logLine = std::format("{:%FT%TZ} {}[{}]: {}\n", std::chrono::system_clock::now(), processName, WSL_PACKAGE_VERSION, Content);
|
||||||
|
|
||||||
|
DWORD bytesWritten{};
|
||||||
|
THROW_IF_WIN32_BOOL_FALSE(WriteFile(file.get(), logLine.c_str(), static_cast<DWORD>(logLine.size()), &bytesWritten, nullptr));
|
||||||
|
}
|
||||||
|
CATCH_LOG();
|
||||||
|
|
||||||
winrt::Windows::Management::Deployment::PackageVolume wsl::windows::common::wslutil::GetSystemVolume()
|
winrt::Windows::Management::Deployment::PackageVolume wsl::windows::common::wslutil::GetSystemVolume()
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@ -181,6 +181,8 @@ UINT UpgradeViaMsi(_In_ LPCWSTR PackageLocation, _In_opt_ LPCWSTR ExtraArgs, _In
|
|||||||
|
|
||||||
UINT UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
|
UINT UninstallViaMsi(_In_opt_ LPCWSTR LogFile, _In_ const std::function<void(INSTALLMESSAGE, LPCWSTR)>& callback);
|
||||||
|
|
||||||
|
void WriteInstallLog(const std::string& Content);
|
||||||
|
|
||||||
winrt::Windows::Management::Deployment::PackageVolume GetSystemVolume();
|
winrt::Windows::Management::Deployment::PackageVolume GetSystemVolume();
|
||||||
|
|
||||||
} // namespace wsl::windows::common::wslutil
|
} // namespace wsl::windows::common::wslutil
|
||||||
|
|||||||
@ -23,6 +23,7 @@ Abstract:
|
|||||||
using unique_msi_handle = wil::unique_any<MSIHANDLE, decltype(MsiCloseHandle), &MsiCloseHandle>;
|
using unique_msi_handle = wil::unique_any<MSIHANDLE, decltype(MsiCloseHandle), &MsiCloseHandle>;
|
||||||
|
|
||||||
using namespace wsl::windows::common::registry;
|
using namespace wsl::windows::common::registry;
|
||||||
|
using namespace wsl::windows::common::wslutil;
|
||||||
|
|
||||||
static constexpr auto c_progIdPrefix{L"App."};
|
static constexpr auto c_progIdPrefix{L"App."};
|
||||||
static constexpr auto c_protocolProgIdSuffix{L".Protocol"};
|
static constexpr auto c_protocolProgIdSuffix{L".Protocol"};
|
||||||
@ -519,6 +520,7 @@ extern "C" UINT __stdcall DeprovisionMsix(MSIHANDLE install)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
WSL_LOG("DeprovisionMsix");
|
WSL_LOG("DeprovisionMsix");
|
||||||
|
WriteInstallLog("MSI install: DeprovisionMsix");
|
||||||
|
|
||||||
const winrt::Windows::Management::Deployment::PackageManager packageManager;
|
const winrt::Windows::Management::Deployment::PackageManager packageManager;
|
||||||
const auto result = packageManager.DeprovisionPackageForAllUsersAsync(wsl::windows::common::wslutil::c_msixPackageFamilyName).get();
|
const auto result = packageManager.DeprovisionPackageForAllUsersAsync(wsl::windows::common::wslutil::c_msixPackageFamilyName).get();
|
||||||
@ -542,6 +544,7 @@ extern "C" UINT __stdcall RemoveMsixAsSystem(MSIHANDLE install)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
WSL_LOG("RemoveMsixAsSystem");
|
WSL_LOG("RemoveMsixAsSystem");
|
||||||
|
WriteInstallLog("MSI install: RemoveMsixAsSystem");
|
||||||
|
|
||||||
const winrt::Windows::Management::Deployment::PackageManager packageManager;
|
const winrt::Windows::Management::Deployment::PackageManager packageManager;
|
||||||
|
|
||||||
@ -571,6 +574,7 @@ extern "C" UINT __stdcall RemoveMsixAsUser(MSIHANDLE install)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
WSL_LOG("RemoveMsixAsUser");
|
WSL_LOG("RemoveMsixAsUser");
|
||||||
|
WriteInstallLog("MSI install: RemoveMsixAsUser");
|
||||||
|
|
||||||
const winrt::Windows::Management::Deployment::PackageManager packageManager;
|
const winrt::Windows::Management::Deployment::PackageManager packageManager;
|
||||||
|
|
||||||
@ -640,6 +644,7 @@ extern "C" UINT __stdcall InstallMsixAsUser(MSIHANDLE install)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
WSL_LOG("InstallMsixAsUser");
|
WSL_LOG("InstallMsixAsUser");
|
||||||
|
WriteInstallLog("MSI install: InstallMsixAsUser");
|
||||||
|
|
||||||
// RegisterPackageByFamilyNameAsync() cannot be run as SYSTEM.
|
// RegisterPackageByFamilyNameAsync() cannot be run as SYSTEM.
|
||||||
// If this thread runs as SYSTEM, simply skip this step.
|
// If this thread runs as SYSTEM, simply skip this step.
|
||||||
@ -683,6 +688,7 @@ try
|
|||||||
msixFile.Handle.reset();
|
msixFile.Handle.reset();
|
||||||
|
|
||||||
WSL_LOG("InstallMsix", TraceLoggingValue(msixFile.Path.c_str(), "Path"));
|
WSL_LOG("InstallMsix", TraceLoggingValue(msixFile.Path.c_str(), "Path"));
|
||||||
|
WriteInstallLog("MSI install: InstallMsix");
|
||||||
|
|
||||||
winrt::Windows::Management::Deployment::PackageManager packageManager;
|
winrt::Windows::Management::Deployment::PackageManager packageManager;
|
||||||
|
|
||||||
@ -780,11 +786,25 @@ catch (...)
|
|||||||
return ERROR_INSTALL_FAILURE;
|
return ERROR_INSTALL_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" UINT __stdcall WslFinalizeInstallation(MSIHANDLE install)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WSL_LOG("WslFinalizeInstallation");
|
||||||
|
WriteInstallLog(std::format("MSI install: WslFinalizeInstallation"));
|
||||||
|
}
|
||||||
|
CATCH_LOG();
|
||||||
|
|
||||||
|
return NOERROR;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" UINT __stdcall WslValidateInstallation(MSIHANDLE install)
|
extern "C" UINT __stdcall WslValidateInstallation(MSIHANDLE install)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
WSL_LOG("WslValidateInstallation");
|
WSL_LOG("WslValidateInstallation");
|
||||||
|
|
||||||
|
WriteInstallLog(std::format("MSI install: WslValidateInstallation"));
|
||||||
|
|
||||||
// TODO: Use a more precise version check so we don't install if the Windows build doesn't support lifted.
|
// TODO: Use a more precise version check so we don't install if the Windows build doesn't support lifted.
|
||||||
|
|
||||||
if (wsl::windows::common::helpers::GetWindowsVersion().BuildNumber < wsl::windows::common::helpers::Vibranium)
|
if (wsl::windows::common::helpers::GetWindowsVersion().BuildNumber < wsl::windows::common::helpers::Vibranium)
|
||||||
|
|||||||
@ -5,6 +5,7 @@ EXPORTS
|
|||||||
CleanMsixState
|
CleanMsixState
|
||||||
DeprovisionMsix
|
DeprovisionMsix
|
||||||
WslValidateInstallation
|
WslValidateInstallation
|
||||||
|
WslFinalizeInstallation
|
||||||
InstallMsix
|
InstallMsix
|
||||||
InstallMsixAsUser
|
InstallMsixAsUser
|
||||||
RegisterLspCategories
|
RegisterLspCategories
|
||||||
|
|||||||
@ -102,7 +102,7 @@ DWORD WINAPI InstallMsiPackage(LPVOID Context)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsUpdateNeeded()
|
std::pair<bool, std::wstring> IsUpdateNeeded()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -115,13 +115,15 @@ bool IsUpdateNeeded()
|
|||||||
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
|
TraceLoggingLevel(WINEVENT_LEVEL_INFO),
|
||||||
TraceLoggingValue(installedVersion.c_str(), "InstalledVersion"));
|
TraceLoggingValue(installedVersion.c_str(), "InstalledVersion"));
|
||||||
|
|
||||||
return installedVersion.empty() || wsl::windows::common::wslutil::ParseWslPackageVersion(installedVersion) < wsl::shared::PackageVersion;
|
return std::make_pair(
|
||||||
|
installedVersion.empty() || wsl::windows::common::wslutil::ParseWslPackageVersion(installedVersion) < wsl::shared::PackageVersion,
|
||||||
|
installedVersion);
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
LOG_CAUGHT_EXCEPTION();
|
LOG_CAUGHT_EXCEPTION();
|
||||||
|
|
||||||
return false;
|
return std::make_pair(false, L"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,11 +134,14 @@ std::shared_ptr<InstallContext> LaunchInstall()
|
|||||||
|
|
||||||
auto lock = mutex.lock_exclusive();
|
auto lock = mutex.lock_exclusive();
|
||||||
|
|
||||||
if (!IsUpdateNeeded())
|
auto [updateNeeded, existingVersion] = IsUpdateNeeded();
|
||||||
|
if (!updateNeeded)
|
||||||
{
|
{
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wsl::windows::common::wslutil::WriteInstallLog(std::format("Starting upgrade via WslInstaller. Previous version: {}", existingVersion));
|
||||||
|
|
||||||
// Return an existing install if any
|
// Return an existing install if any
|
||||||
if (auto ptr = weak_context.lock(); ptr != nullptr)
|
if (auto ptr = weak_context.lock(); ptr != nullptr)
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user