Poll for the result of operations during MSI installation (#41415)
* Poll for the result of operations during MSI installation * Cleanup
Blue committed
Aug 21, 2026 at 23:47 UTC
780845097a33b8937d7f831870e8fc228b1feb19
1 file changed
+33
-8
src/windows/wslinstall/DllMain.cpp
+33
-8
@@ -75,18 +75,42 @@ void TrustPackageCertificate(LPCWSTR Path)
75
}
76
#endif
77
78
-void ThrowIfOperationError(
79
- const winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Windows::Management::Deployment::DeploymentResult, winrt::Windows::Management::Deployment::DeploymentProgress>& result,
78
+winrt::Windows::Management::Deployment::DeploymentResult WaitForDeploymentOperation(
79
+ const winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Windows::Management::Deployment::DeploymentResult, winrt::Windows::Management::Deployment::DeploymentProgress>& operation,
80
const std::source_location& source = std::source_location::current())
81
{
82
- const auto status = result.get();
82
+ // IAsyncOperation::get() installs a completion delegate whose implementation resides in this DLL. The operation can retain
83
+ // that delegate after get() returns, allowing its final Release() to call into the DLL after MSI unloads it.
84
+ // To avoid this, poll until the operation is completed.
85
+ auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [&]() { operation.Close(); });
86
+
87
+ auto status = operation.Status();
88
+ while (status == winrt::Windows::Foundation::AsyncStatus::Started)
89
+ {
90
+ Sleep(10);
91
+ status = operation.Status();
92
+ }
93
+
94
+ if (status == winrt::Windows::Foundation::AsyncStatus::Error)
95
+ {
96
+ const auto error = operation.ErrorCode();
97
+ THROW_HR_MSG(error, "Source: %hs() - %hs:%lu", source.function_name(), source.file_name(), source.line());
98
+ }
99
84
- if (result.Status() == winrt::Windows::Foundation::AsyncStatus::Error)
100
+ if (status == winrt::Windows::Foundation::AsyncStatus::Canceled)
101
{
86
- THROW_HR_MSG(result.ErrorCode(), "Source: %hs() - %hs:%lu", source.function_name(), source.file_name(), source.line());
102
+ throw winrt::hresult_canceled();
103
}
104
89
- THROW_IF_FAILED_MSG(status.ExtendedErrorCode(), "%ls", status.ErrorText().c_str());
105
+ return operation.GetResults();
106
+}
107
+
108
+void ThrowIfOperationError(
109
+ const winrt::Windows::Foundation::IAsyncOperationWithProgress<winrt::Windows::Management::Deployment::DeploymentResult, winrt::Windows::Management::Deployment::DeploymentProgress>& operation,
110
+ const std::source_location& source = std::source_location::current())
111
+{
112
+ const auto result = WaitForDeploymentOperation(operation, source);
113
+ THROW_IF_FAILED_MSG(result.ExtendedErrorCode(), "%ls", result.ErrorText().c_str());
114
}
115
116
std::wstring GetMsiProperty(MSIHANDLE install, LPCWSTR name)
@@ -530,7 +554,8 @@ try
554
WSL_INSTALL_LOG("DeprovisionMsix");
555
556
const winrt::Windows::Management::Deployment::PackageManager packageManager;
533
- const auto result = packageManager.DeprovisionPackageForAllUsersAsync(wsl::windows::common::wslutil::c_msixPackageFamilyName).get();
557
+ const auto result = WaitForDeploymentOperation(
558
+ packageManager.DeprovisionPackageForAllUsersAsync(wsl::windows::common::wslutil::c_msixPackageFamilyName));
559
LOG_IF_FAILED_MSG(result.ExtendedErrorCode(), "%ls", result.ErrorText().c_str());
560
561
return NOERROR;
@@ -1013,4 +1038,4 @@ EXTERN_C BOOL STDAPICALLTYPE DllMain(_In_ HINSTANCE Instance, _In_ DWORD Reason,
1038
}
1039
1040
return TRUE;
1016
-}
\ No newline at end of file
1041
+}