diff --git a/installer/PowerToysSetup/Product.wxs b/installer/PowerToysSetup/Product.wxs
index 89faee4a75..8fd73068e0 100644
--- a/installer/PowerToysSetup/Product.wxs
+++ b/installer/PowerToysSetup/Product.wxs
@@ -91,9 +91,19 @@
NOT Installed
+
+
+
+
+
+
+
@@ -695,6 +708,7 @@
+
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp
index 5c03294d6c..7f55813851 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.cpp
+++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp
@@ -630,6 +630,84 @@ UINT __stdcall DetectPrevInstallPathCA(MSIHANDLE hInstall)
return WcaFinalize(er);
}
+
+UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
+{
+ HRESULT hr = S_OK;
+ UINT er = ERROR_SUCCESS;
+ hr = WcaInitialize(hInstall, "TerminateProcessesCA");
+
+ std::vector processes;
+ const size_t maxProcesses = 4096;
+ DWORD bytes = maxProcesses * sizeof(processes[0]);
+ processes.resize(maxProcesses);
+
+ if (!EnumProcesses(processes.data(), bytes, &bytes))
+ {
+ return 1;
+ }
+ processes.resize(bytes / sizeof(processes[0]));
+
+ std::array processesToTerminate = {
+ L"PowerLauncher.exe",
+ L"Microsoft.PowerToys.Settings.UI.Runner.exe",
+ L"Microsoft.PowerToys.Settings.UI.exe",
+ L"PowerToys.exe"
+ };
+
+ for (const auto procID : processes)
+ {
+ if (!procID)
+ {
+ continue;
+ }
+ wchar_t processName[MAX_PATH] = L"";
+
+ HANDLE hProcess{OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE, FALSE, procID)};
+ if (!hProcess)
+ {
+ continue;
+ }
+ HMODULE hMod;
+ DWORD cbNeeded;
+
+ if (!EnumProcessModules(hProcess, &hMod, sizeof(hMod), &cbNeeded))
+ {
+ CloseHandle(hProcess);
+ continue;
+ }
+ GetModuleBaseNameW(hProcess, hMod, processName, sizeof(processName) / sizeof(wchar_t));
+
+ for (const auto processToTerminate : processesToTerminate)
+ {
+ if (processName == processToTerminate)
+ {
+ const DWORD timeout = 500;
+ auto windowEnumerator = [](HWND hwnd, LPARAM procIDPtr) -> BOOL {
+ auto targetProcID = *reinterpret_cast(procIDPtr);
+ DWORD windowProcID = 0;
+ GetWindowThreadProcessId(hwnd, &windowProcID);
+ if (windowProcID == targetProcID)
+ {
+ DWORD_PTR _ {};
+ SendMessageTimeoutA(hwnd, WM_CLOSE, 0, 0, SMTO_BLOCK, timeout, &_);
+ }
+ return TRUE;
+ };
+ EnumWindows(windowEnumerator, reinterpret_cast(&procID));
+ Sleep(timeout);
+ TerminateProcess(hProcess, 0);
+ break;
+ }
+ }
+ CloseHandle(hProcess);
+ }
+
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+ return WcaFinalize(er);
+}
+
+
// DllMain - Initialize and cleanup WiX custom action utils.
extern "C" BOOL WINAPI DllMain(__in HINSTANCE hInst, __in ULONG ulReason, __in LPVOID)
{
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.def b/installer/PowerToysSetupCustomActions/CustomAction.def
index be33fd02d4..3e8a2ab72e 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.def
+++ b/installer/PowerToysSetupCustomActions/CustomAction.def
@@ -11,4 +11,5 @@ EXPORTS
TelemetryLogUninstallCancelCA
TelemetryLogUninstallFailCA
TelemetryLogRepairCancelCA
- TelemetryLogRepairFailCA
\ No newline at end of file
+ TelemetryLogRepairFailCA
+ TerminateProcessesCA
\ No newline at end of file
diff --git a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
index b36a7f3978..0e5cfb8c4e 100644
--- a/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
+++ b/installer/PowerToysSetupCustomActions/PowerToysSetupCustomActions.vcxproj
@@ -61,7 +61,7 @@
true
- Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)
+ Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)
$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories)
CustomAction.def
true
@@ -84,7 +84,7 @@
true
- Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)
+ Psapi.lib;Pathcch.lib;comsupp.lib;taskschd.lib;Secur32.lib;msi.lib;dutil.lib;wcautil.lib;Version.lib;%(AdditionalDependencies)
$(WIX)sdk\$(WixPlatformToolset)\lib\x64;$(SolutionDir)\packages\WiX.3.11.2\tools\sdk\vs2017\lib\x64;%(AdditionalLibraryDirectories)
CustomAction.def
true
diff --git a/installer/PowerToysSetupCustomActions/stdafx.h b/installer/PowerToysSetupCustomActions/stdafx.h
index 91ff9d5eb3..b53439bd31 100644
--- a/installer/PowerToysSetupCustomActions/stdafx.h
+++ b/installer/PowerToysSetupCustomActions/stdafx.h
@@ -1,6 +1,7 @@
#pragma once
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define DPSAPI_VERSION 1
// Windows Header Files:
#include
#include
@@ -21,3 +22,7 @@
#include
#include
#include
+
+#include
+#include
+#include
diff --git a/src/action_runner/action_runner.cpp b/src/action_runner/action_runner.cpp
index 61dba78627..94ad07f228 100644
--- a/src/action_runner/action_runner.cpp
+++ b/src/action_runner/action_runner.cpp
@@ -139,8 +139,8 @@ bool dotnet_is_installed()
bool install_dotnet()
{
- const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/a1510e74-b31a-4434-b8a0-8074ff31fb3f/b7de8ecba4a14d8312551cfdc745dea1/windowsdesktop-runtime-3.1.0-win-x64.exe";
- const wchar_t DOTNET_DESKTOP_FILENAME[] = L"windowsdesktop-runtime-3.1.0-win-x64.exe";
+ const wchar_t DOTNET_DESKTOP_DOWNLOAD_LINK[] = L"https://download.visualstudio.microsoft.com/download/pr/d8cf1fe3-21c2-4baf-988f-f0152996135e/0c00b94713ee93e7ad5b4f82e2b86607/windowsdesktop-runtime-3.1.4-win-x64.exe";
+ const wchar_t DOTNET_DESKTOP_FILENAME[] = L"windowsdesktop-runtime-3.1.4-win-x64.exe";
auto dotnet_download_path = fs::temp_directory_path() / DOTNET_DESKTOP_FILENAME;
winrt::Windows::Foundation::Uri download_link{ DOTNET_DESKTOP_DOWNLOAD_LINK };