Avoid stop service race window during uninstall (#40625)
Disable service before stopping service during uninstall.
Feng Wang committed
Jun 1, 2026 at 10:14 UTC
c28bd152e9be65003bf602db2756c168add7114b
3 files changed
+57
-1
msipackage/package.wix.in
+10
@@ -620,6 +620,11 @@
620
<CustomAction Id="InstallMsix.SetProperty" Return="check" Property="InstallMsix" Value='[DATABASE]' Execute='immediate' />
621
<CustomAction Id="CalculateWslSettingsProtocolIds" Impersonate="no" BinaryRef="wslinstall.dll" DllEntry="CalculateWslSettingsProtocolIds" Return="check" Execute='immediate' />
622
623
+ <!-- Disable WSLService before StopServices so SCM rejects activation attempts
624
+ from COM clients while it is being stopped on uninstall. -->
625
+ <CustomAction Id="DisableWslService" Impersonate="no" BinaryRef="wslinstall.dll" DllEntry="DisableWslService" Return="ignore" Execute="deferred" />
626
+ <CustomAction Id="EnableWslService" Impersonate="no" BinaryRef="wslinstall.dll" DllEntry="EnableWslService" Return="ignore" Execute="rollback" />
627
+
628
<!-- See https://learn.microsoft.com/en-us/windows/win32/msi/examples-of-conditional-statement-syntax -->
629
<InstallExecuteSequence>
630
<Custom Action="ValidateInstall" After="InstallInitialize" Condition="(not INSTALLED) and (not SKIPVALIDATION = 1)" />
@@ -675,6 +680,11 @@
680
681
<Custom Action="FinalizeInstall" After="PublishFeatures"/>
682
683
+ <!-- Rollback CA must be sequenced before the forward action so it is registered
684
+ in the rollback script first. -->
685
+ <Custom Action="EnableWslService" Before="DisableWslService" Condition='REMOVE~="ALL"' />
686
+ <Custom Action="DisableWslService" Before="StopServices" Condition='REMOVE~="ALL"' />
687
+
688
</InstallExecuteSequence>
689
690
<!-- Don't show a 'Modify' button in settings since there is nothing to modify -->
src/windows/wslinstall/DllMain.cpp
+44
@@ -940,6 +940,50 @@ extern "C" UINT __stdcall CalculateWslSettingsProtocolIds(MSIHANDLE install)
940
return NOERROR;
941
}
942
943
+static void SetWslServiceStartType(DWORD StartType)
944
+{
945
+ const wil::unique_schandle manager{OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CONNECT)};
946
+ THROW_LAST_ERROR_IF(!manager);
947
+
948
+ const wil::unique_schandle service{OpenServiceW(manager.get(), L"WSLService", SERVICE_CHANGE_CONFIG)};
949
+ if (!service)
950
+ {
951
+ const auto error = GetLastError();
952
+ if (error == ERROR_SERVICE_DOES_NOT_EXIST)
953
+ {
954
+ return;
955
+ }
956
+ THROW_WIN32(error);
957
+ }
958
+
959
+ THROW_IF_WIN32_BOOL_FALSE(ChangeServiceConfigW(
960
+ service.get(), SERVICE_NO_CHANGE, StartType, SERVICE_NO_CHANGE, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
961
+}
962
+
963
+extern "C" UINT __stdcall DisableWslService(MSIHANDLE install)
964
+{
965
+ try
966
+ {
967
+ WSL_INSTALL_LOG("DisableWslService");
968
+ SetWslServiceStartType(SERVICE_DISABLED);
969
+ }
970
+ CATCH_LOG();
971
+
972
+ return NOERROR;
973
+}
974
+
975
+extern "C" UINT __stdcall EnableWslService(MSIHANDLE install)
976
+{
977
+ try
978
+ {
979
+ WSL_INSTALL_LOG("EnableWslService");
980
+ SetWslServiceStartType(SERVICE_AUTO_START);
981
+ }
982
+ CATCH_LOG();
983
+
984
+ return NOERROR;
985
+}
986
+
987
EXTERN_C BOOL STDAPICALLTYPE DllMain(_In_ HINSTANCE Instance, _In_ DWORD Reason, _In_opt_ LPVOID Reserved)
988
{
989
wil::DLLMain(Instance, Reason, Reserved);
src/windows/wslinstall/wslinstall.def
+3
-1
@@ -13,4 +13,6 @@ EXPORTS
13
RemoveMsixAsUser
14
RemoveRegistryKeyProtections
15
UnregisterLspCategories
16
- CalculateWslSettingsProtocolIds
\ No newline at end of file
16
+ CalculateWslSettingsProtocolIds
17
+ DisableWslService
18
+ EnableWslService
\ No newline at end of file