From 665851300dd0adbbbc338788314dcfbb4a10e50b Mon Sep 17 00:00:00 2001
From: Stefan Markovic <57057282+stefansjfw@users.noreply.github.com>
Date: Tue, 27 Sep 2022 19:04:04 +0200
Subject: [PATCH] [Installer]Self-contained WinAppSDK & VC Redist using
hardlinks (#19992)
* [POC] WinAppSDK dlls symlinks
* Update expect.txt
* Remove dll
* Use hard links
* WIP vcredist self-contained
* Cleanup
* Error check
* Revert version change
---
.github/actions/spell-check/expect.txt | 1 +
installer/PowerToysSetup/PowerToys.wxs | 28 ---
installer/PowerToysSetup/Product.wxs | 119 +++++++--
.../CustomAction.cpp | 225 ++++++++++++++++++
.../CustomAction.def | 4 +
src/common/interop/PowerToys.Interop.vcxproj | 3 +
6 files changed, 337 insertions(+), 43 deletions(-)
diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt
index 6a389cab2c..d99ef2c045 100644
--- a/.github/actions/spell-check/expect.txt
+++ b/.github/actions/spell-check/expect.txt
@@ -2006,6 +2006,7 @@ swprintf
SWRESTORE
swscanf
SYMED
+symlink
SYMOPT
SYNCMFT
SYNCPAINT
diff --git a/installer/PowerToysSetup/PowerToys.wxs b/installer/PowerToysSetup/PowerToys.wxs
index 10a90dcda6..37ea295681 100644
--- a/installer/PowerToysSetup/PowerToys.wxs
+++ b/installer/PowerToysSetup/PowerToys.wxs
@@ -10,10 +10,6 @@
-
-
-
-
@@ -24,10 +20,6 @@
-
-
-
-
@@ -69,8 +61,6 @@
DetectedWindowsBuildNumber >= 19041 OR WixBundleInstalled
-
-
-
-
-
-
-
+
-
+
-
+
@@ -113,19 +113,23 @@
-
+
-
+
+
+
+
+
-
+
+
+
+
+
NOT Installed and CREATESCHEDULEDTASK = 1
NOT Installed
+
+ NOT Installed
+
+
+ NOT Installed
+
@@ -244,6 +258,12 @@
Installed AND (REMOVE="ALL")
+
+ Installed AND (REMOVE="ALL")
+
+
+ Installed AND (REMOVE="ALL")
+
+
+
+
+
+
+
+
+
-
@@ -415,6 +482,10 @@
+
+
+
+
@@ -617,9 +688,6 @@
-
-
-
@@ -669,6 +737,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -906,7 +990,7 @@
-
+
@@ -926,7 +1010,7 @@
-
+
@@ -936,7 +1020,7 @@
-
+
@@ -1089,7 +1173,6 @@
-
@@ -1168,6 +1251,12 @@
+
+
+
+
+
+
@@ -1828,7 +1917,7 @@
-
+
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.cpp b/installer/PowerToysSetupCustomActions/CustomAction.cpp
index 764b1a0067..57df075882 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.cpp
+++ b/installer/PowerToysSetupCustomActions/CustomAction.cpp
@@ -32,6 +32,56 @@ const DWORD USERNAME_LEN = UNLEN + 1; // User Name + '\0'
static const wchar_t* POWERTOYS_EXE_COMPONENT = L"{A2C66D91-3485-4D00-B04D-91844E6B345B}";
static const wchar_t* POWERTOYS_UPGRADE_CODE = L"{42B84BF7-5FBF-473B-9C8B-049DC16F7708}";
+const std::vector winAppSdkFiles = {
+ L"CoreMessagingXP.dll",
+ L"DWriteCore.dll",
+ L"DwmSceneI.dll",
+ L"MRM.dll",
+ L"Microsoft.DirectManipulation.dll",
+ L"Microsoft.InputStateManager.dll",
+ L"Microsoft.Internal.FrameworkUdk.dll",
+ L"Microsoft.UI.Composition.OSSupport.dll",
+ L"Microsoft.UI.Input.dll",
+ L"Microsoft.UI.Windowing.Core.dll",
+ L"Microsoft.UI.Xaml.Controls.dll",
+ L"Microsoft.UI.Xaml.Controls.pri",
+ L"Microsoft.UI.Xaml.Internal.dll",
+ L"Microsoft.UI.Xaml.Phone.dll",
+ L"Microsoft.Web.WebView2.Core.dll",
+ L"Microsoft.Windows.AppNotifications.Projection.dll",
+ L"Microsoft.Windows.ApplicationModel.Resources.dll",
+ L"Microsoft.WindowsAppRuntime.Bootstrap.dll",
+ L"Microsoft.Windows.PushNotifications.Projection.dll",
+ L"Microsoft.Windows.System.Projection.dll",
+ L"Microsoft.WindowsAppRuntime.Insights.Resource.dll",
+ L"Microsoft.WindowsAppRuntime.Release.Net.dll",
+ L"Microsoft.WindowsAppRuntime.dll",
+ L"Microsoft.ui.xaml.dll",
+ L"Microsoft.ui.xaml.resources.19h1.dll",
+ L"Microsoft.ui.xaml.resources.common.dll",
+ L"PushNotificationsLongRunningTask.ProxyStub.dll",
+ L"WinUIEdit.dll",
+ L"WindowsAppRuntime.png",
+ L"WindowsAppSdk.AppxDeploymentExtensions.Desktop.dll",
+ L"dcompi.dll",
+ L"dwmcorei.dll",
+ L"marshal.dll",
+ L"wuceffectsi.dll" };
+
+const std::vector powerToysInteropFiles = {
+ L"concrt140.dll",
+ L"msvcp140.dll",
+ L"msvcp140_1.dll",
+ L"msvcp140_2.dll",
+ L"msvcp140_atomic_wait.dll",
+ L"msvcp140_codecvt_ids.dll",
+ L"PowerToys.Interop.dll",
+ L"vcamp140.dll",
+ L"vccorlib140.dll",
+ L"vcomp140.dll",
+ L"vcruntime140.dll",
+ L"vcruntime140_1.dll" };
+
struct WcaSink : spdlog::sinks::base_sink
{
virtual void sink_it_(const spdlog::details::log_msg& msg) override
@@ -995,6 +1045,181 @@ UINT __stdcall UnRegisterContextMenuPackagesCA(MSIHANDLE hInstall)
return WcaFinalize(er);
}
+UINT __stdcall CreateWinAppSDKHardlinksCA(MSIHANDLE hInstall)
+{
+ HRESULT hr = S_OK;
+ UINT er = ERROR_SUCCESS;
+ std::wstring installationFolder, winAppSDKFilesSrcDir, settingsDir, powerRenameDir;
+
+ hr = WcaInitialize(hInstall, "CreateWinAppSDKHardlinksCA");
+ ExitOnFailure(hr, "Failed to initialize");
+
+ hr = getInstallFolder(hInstall, installationFolder);
+ ExitOnFailure(hr, "Failed to get installation folder");
+
+ winAppSDKFilesSrcDir = installationFolder + L"dll\\WinAppSDK\\";
+ settingsDir = installationFolder + L"Settings\\";
+ powerRenameDir = installationFolder + L"modules\\PowerRename\\";
+
+ for (auto file : winAppSdkFiles)
+ {
+ std::error_code ec;
+ std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (settingsDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((winAppSDKFilesSrcDir + file).c_str(), (powerRenameDir + file).c_str(), ec);
+
+ if (ec.value() != S_OK)
+ {
+ std::wstring errorMessage{ L"Error creating hard link for: " };
+ errorMessage += file;
+ errorMessage += L", error code: " + std::to_wstring(ec.value());
+ Logger::error(errorMessage);
+ }
+ }
+
+LExit:
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+ return WcaFinalize(er);
+}
+
+UINT __stdcall CreatePTInteropHardlinksCA(MSIHANDLE hInstall)
+{
+ HRESULT hr = S_OK;
+ UINT er = ERROR_SUCCESS;
+ std::wstring installationFolder, interopFilesSrcDir, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
+ imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir;
+
+ hr = WcaInitialize(hInstall, "CreatePTInteropHardlinksCA");
+ ExitOnFailure(hr, "Failed to initialize");
+
+ hr = getInstallFolder(hInstall, installationFolder);
+ ExitOnFailure(hr, "Failed to get installation folder");
+
+ interopFilesSrcDir = installationFolder + L"dll\\Interop\\";
+ colorPickerDir = installationFolder + L"modules\\ColorPicker\\";
+ powerOCRDir = installationFolder + L"modules\\PowerOCR\\";
+ launcherDir = installationFolder + L"modules\\launcher\\";
+ fancyZonesDir = installationFolder + L"modules\\FancyZones\\";
+ imageResizerDir = installationFolder + L"modules\\ImageResizer\\";
+ settingsDir = installationFolder + L"Settings\\";
+ awakeDir = installationFolder + L"modules\\Awake\\";
+ measureToolDir = installationFolder + L"modules\\MeasureTool\\";
+ powerAccentDir = installationFolder + L"modules\\PowerAccent\\";
+
+ for (auto file : powerToysInteropFiles)
+ {
+ std::error_code ec;
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (colorPickerDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (powerOCRDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (launcherDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (fancyZonesDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (imageResizerDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (settingsDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (awakeDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (measureToolDir + file).c_str(), ec);
+ std::filesystem::create_hard_link((interopFilesSrcDir + file).c_str(), (powerAccentDir + file).c_str(), ec);
+
+ if (ec.value() != S_OK)
+ {
+ std::wstring errorMessage{ L"Error creating hard link for: " };
+ errorMessage += file;
+ errorMessage += L", error code: " + std::to_wstring(ec.value());
+ Logger::error(errorMessage);
+ }
+ }
+
+LExit:
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+ return WcaFinalize(er);
+}
+
+UINT __stdcall DeleteWinAppSDKHardlinksCA(MSIHANDLE hInstall)
+{
+ HRESULT hr = S_OK;
+ UINT er = ERROR_SUCCESS;
+ std::wstring installationFolder, settingsDir, powerRenameDir;
+
+ hr = WcaInitialize(hInstall, "DeleteWinAppSDKHardlinksCA");
+ ExitOnFailure(hr, "Failed to initialize");
+
+ hr = getInstallFolder(hInstall, installationFolder);
+ ExitOnFailure(hr, "Failed to get installation folder");
+
+ settingsDir = installationFolder + L"Settings\\";
+ powerRenameDir = installationFolder + L"modules\\PowerRename\\";
+
+ try
+ {
+ for (auto file : winAppSdkFiles)
+ {
+ DeleteFile((settingsDir + file).c_str());
+ DeleteFile((powerRenameDir + file).c_str());
+ }
+ }
+ catch (std::exception e)
+ {
+ std::string errorMessage{ "Exception thrown while trying to delete WAS hardlinks: " };
+ errorMessage += e.what();
+ Logger::error(errorMessage);
+
+ er = ERROR_INSTALL_FAILURE;
+ }
+
+LExit:
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+ return WcaFinalize(er);
+}
+
+UINT __stdcall DeletePTInteropHardlinksCA(MSIHANDLE hInstall)
+{
+ HRESULT hr = S_OK;
+ UINT er = ERROR_SUCCESS;
+ std::wstring installationFolder, interopFilesSrcDir, colorPickerDir, powerOCRDir, launcherDir, fancyZonesDir,
+ imageResizerDir, settingsDir, awakeDir, measureToolDir, powerAccentDir;
+
+ hr = WcaInitialize(hInstall, "DeletePTInteropHardlinksCA");
+ ExitOnFailure(hr, "Failed to initialize");
+
+ hr = getInstallFolder(hInstall, installationFolder);
+ ExitOnFailure(hr, "Failed to get installation folder");
+
+ colorPickerDir = installationFolder + L"modules\\ColorPicker\\";
+ powerOCRDir = installationFolder + L"modules\\PowerOCR\\";
+ launcherDir = installationFolder + L"modules\\launcher\\";
+ fancyZonesDir = installationFolder + L"modules\\FancyZones\\";
+ imageResizerDir = installationFolder + L"modules\\ImageResizer\\";
+ settingsDir = installationFolder + L"Settings\\";
+ awakeDir = installationFolder + L"modules\\Awake\\";
+ measureToolDir = installationFolder + L"modules\\MeasureTool\\";
+ powerAccentDir = installationFolder + L"modules\\PowerAccent\\";
+
+ try
+ {
+ for (auto file : powerToysInteropFiles)
+ {
+ DeleteFile((colorPickerDir + file).c_str());
+ DeleteFile((powerOCRDir + file).c_str());
+ DeleteFile((launcherDir + file).c_str());
+ DeleteFile((fancyZonesDir + file).c_str());
+ DeleteFile((imageResizerDir + file).c_str());
+ DeleteFile((settingsDir + file).c_str());
+ DeleteFile((awakeDir + file).c_str());
+ DeleteFile((measureToolDir + file).c_str());
+ DeleteFile((powerAccentDir + file).c_str());
+ }
+ }
+ catch (std::exception e)
+ {
+ std::string errorMessage{ "Exception thrown while trying to delete PowerToys Interop and VC Redist hardlinks: " };
+ errorMessage += e.what();
+ Logger::error(errorMessage);
+
+ er = ERROR_INSTALL_FAILURE;
+ }
+
+LExit:
+ er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
+ return WcaFinalize(er);
+}
UINT __stdcall TerminateProcessesCA(MSIHANDLE hInstall)
{
diff --git a/installer/PowerToysSetupCustomActions/CustomAction.def b/installer/PowerToysSetupCustomActions/CustomAction.def
index 255b64724e..3a36f02f7d 100644
--- a/installer/PowerToysSetupCustomActions/CustomAction.def
+++ b/installer/PowerToysSetupCustomActions/CustomAction.def
@@ -3,6 +3,10 @@ LIBRARY "PowerToysSetupCustomActions"
EXPORTS
ApplyModulesRegistryChangeSetsCA
CreateScheduledTaskCA
+ CreateWinAppSDKHardlinksCA
+ DeleteWinAppSDKHardlinksCA
+ CreatePTInteropHardlinksCA
+ DeletePTInteropHardlinksCA
DetectPrevInstallPathCA
RemoveScheduledTasksCA
TelemetryLogInstallSuccessCA
diff --git a/src/common/interop/PowerToys.Interop.vcxproj b/src/common/interop/PowerToys.Interop.vcxproj
index 8e4e47f6a0..e93b0490d3 100644
--- a/src/common/interop/PowerToys.Interop.vcxproj
+++ b/src/common/interop/PowerToys.Interop.vcxproj
@@ -51,6 +51,9 @@
PowerToys.Interop
$(SolutionDir)$(Platform)\$(Configuration)\
+
+ true
+
MultiThreadedDebugDLL