devicehost: stop re-signing and fix MSI installer failing to replace wsldevicehost.dll (#40075)

* devicehost: stop re-signing and fix MSI installer failing to replace wsldevicehost.dll * pr feedback * use MSIRMSHUTDOWN = 1 instead of custom action --------- Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>

Ben Hillis committed Apr 6, 2026 at 15:10 UTC f9f1c38d9f42e2a19b2153500d94290ba6a89dc9
5 files changed +16 -5
.pipelines/build-stage.yml
+1 -1
@@ -24,7 +24,7 @@ parameters:
24 type: object
25 default:
26 - target: "wsl;libwsl;wslg;wslservice;wslhost;wslrelay;wslinstaller;wslinstall;initramfs;wslserviceproxystub;wslsettings;wslinstallerproxystub;testplugin"
27 - pattern: "wsl.exe,libwsl.dll,wslg.exe,wslservice.exe,wslhost.exe,wslrelay.exe,wslinstaller.exe,wslinstall.dll,wslserviceproxystub.dll,wslsettings/wslsettings.dll,wslsettings/wslsettings.exe,wslinstallerproxystub.dll,wsldevicehost.dll,WSLDVCPlugin.dll,testplugin.dll,wsldeps.dll"
27 + pattern: "wsl.exe,libwsl.dll,wslg.exe,wslservice.exe,wslhost.exe,wslrelay.exe,wslinstaller.exe,wslinstall.dll,wslserviceproxystub.dll,wslsettings/wslsettings.dll,wslsettings/wslsettings.exe,wslinstallerproxystub.dll,WSLDVCPlugin.dll,testplugin.dll,wsldeps.dll"
28 - target: "msixgluepackage"
29 pattern: "gluepackage.msix"
30 - target: "msipackage"
CMakeLists.txt
-1
@@ -157,7 +157,6 @@ set (GENERATED_DIR ${CMAKE_BINARY_DIR}/generated)
157 file(MAKE_DIRECTORY ${GENERATED_DIR})
158
159 set(PACKAGE_CERTIFICATE ${GENERATED_DIR}/dev-cert.pfx)
160 -file(CREATE_LINK ${WSL_DEVICE_HOST_SOURCE_DIR}/bin/${TARGET_PLATFORM}/wsldevicehost.dll ${BIN}/wsldevicehost.dll)
160 file(CREATE_LINK ${WSLG_SOURCE_DIR}/${TARGET_PLATFORM}/${WSLG_TS_PLUGIN_DLL} ${BIN}/${WSLG_TS_PLUGIN_DLL})
161 file(CREATE_LINK ${WSLDEPS_SOURCE_DIR}/bin/wsldeps.dll ${BIN}/wsldeps.dll)
162
msipackage/package.wix.in
+3 -2
@@ -221,6 +221,8 @@
221 N.B. It shouldn't be started on install because it will fail to start if the OC is missing,
222 which would fail the install. -->
223 <ServiceControl Id="StopService" Stop="both" Remove="uninstall" Name="WSLService" Wait="yes" />
224 +
225 + <File Id="wsldevicehost.dll" Source="${WSL_DEVICE_HOST_SOURCE_DIR}/bin/${TARGET_PLATFORM}/wsldevicehost.dll" />
226 </Component>
227
228 <Component Id="wslg" Guid="F0C8D6BA-1502-41E7-BF72-D93DFA134731" UninstallWhenSuperseded="yes" DisableRegistryReflection="yes" Bitness="always64">
@@ -232,7 +234,6 @@
234 <File Id="rdpnanoTransport.dll" Source="${MSRDC_SOURCE_DIR}/${TARGET_PLATFORM}/rdpnanoTransport.dll" />
235 <File Id="RdpWinStlHelper.dll" Source="${MSRDC_SOURCE_DIR}/${TARGET_PLATFORM}/RdpWinStlHelper.dll" />
236 <?endif?>
235 - <File Id="wsldevicehost.dll" Source="${PACKAGE_INPUT_DIR}/wsldevicehost.dll" />
237 <File Id="${WSLG_TS_PLUGIN_DLL}" Source="${PACKAGE_INPUT_DIR}/${WSLG_TS_PLUGIN_DLL}" />
238
239 <!-- MSRDC Plugin registration -->
@@ -551,7 +552,7 @@
552 <!-- Force all applications to exit during upgrade.
553 See: https://learn.microsoft.com/en-us/windows/win32/msi/msirmshutdown
554 -->
554 - <Property Id="MSIRMSHUTDOWN" Value="0" Secure="yes" />
555 + <Property Id="MSIRMSHUTDOWN" Value="1" Secure="yes" />
556 </Package>
557 </Wix>
558
packages.config
+1 -1
@@ -18,7 +18,7 @@
18 <package id="Microsoft.WSL.bsdtar" version="0.0.2-2" />
19 <package id="Microsoft.WSL.Dependencies.amd64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
20 <package id="Microsoft.WSL.Dependencies.arm64fre" version="10.0.27820.1000-250318-1700.rs-base2-hyp" targetFramework="native" />
21 - <package id="Microsoft.WSL.DeviceHost" version="1.1.48-0" />
21 + <package id="Microsoft.WSL.DeviceHost" version="1.2.10-0" />
22 <package id="Microsoft.WSL.Kernel" version="6.6.114.1-1" targetFramework="native" />
23 <package id="Microsoft.WSL.LinuxSdk" version="1.20.0" targetFramework="native" />
24 <package id="Microsoft.WSL.TestDistro" version="2.7.1-1" />
test/windows/InstallerTests.cpp
+11
@@ -175,8 +175,17 @@ class InstallerTests
175 return wsl::windows::common::registry::ReadString(m_lxssKey.get(), L"MSI", L"ProductCode", L"");
176 }
177
178 + // Release any in-process COM DLLs (e.g. wslserviceproxystub.dll loaded by prior tests)
179 + // so the Restart Manager doesn't detect the test process as holding files.
180 + // This avoids install failures on older Server SKUs where the RM has stricter silent-mode behavior.
181 + static void PrepareForMsiOperation()
182 + {
183 + CoFreeUnusedLibrariesEx(0, 0);
184 + }
185 +
186 void UninstallMsi()
187 {
188 + PrepareForMsiOperation();
189 auto productCode = GetMsiProductCode();
190 VERIFY_IS_FALSE(productCode.empty());
191
@@ -185,6 +194,7 @@ class InstallerTests
194
195 void InstallMsi()
196 {
197 + PrepareForMsiOperation();
198 CallMsiExec(std::format(L"/qn /norestart /i {} /L*V {}", m_msiPath, GenerateMsiLogPath()));
199 }
200
@@ -367,6 +377,7 @@ class InstallerTests
377 LogInfo("Installing: %ls", installerFile.c_str());
378 if (wsl::shared::string::EndsWith<wchar_t>(installerFile, L".msi"))
379 {
380 + PrepareForMsiOperation();
381 CallMsiExec(std::format(L"/qn /norestart /i {} /L*V {}", installerFile, GenerateMsiLogPath()));
382 }
383 else