mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-05-18 05:05:25 +02:00
## Summary of the Pull Request Two related installer changes to (1) eliminate genuinely-unused dependencies and (2) deduplicate shared WinAppSDK files between `<install>\` and `<install>\WinUI3Apps\` to shrink the installer download. ### 1. Remove unused dependencies (~11 MB savings per output location) - **System.Data.SqlClient**: Removed from MouseWithoutBorders projects and the central `Directory.Packages.props` pin. It was a transitive dependency of `Microsoft.Windows.Compatibility` but PowerToys has zero SQL database usage. - **Unused `using` import**: Removed `using System.ServiceModel.Channels` from MouseWithoutBorders `Program.cs` (no WCF usage). - **MFC / C++ AMP / OpenMP DLLs**: Added `RemoveUnusedVCRuntimeDlls` target in `Directory.Build.targets` to clean up `mfc140*`, `mfcm140*`, `vcamp140*`, and `vcomp140*` DLLs that leak from the VC++ Redistributable tree but are not imported by any PowerToys binary (verified with `dumpbin /dependents` across all installed binaries). Also excluded MFC DLLs from installer file collection. ### 2. WinAppSDK file deduplication (build-time only; install-time uses copy) **Background**: The `WinUI3Apps` subfolder must remain a real directory because MSIX sparse package registration applies DACL changes to the `ExternalLocation` folder (PR #47177). Flattening is not viable. **Build-time** (`generateAllFileComponents.ps1`): computes the SHA256 intersection of root and `WinUI3Apps` files, and for each file that is also present in the BaseApplications WXS file list, removes the duplicate from the WinUI3Apps WXS component list and writes its name to a `hardlinks.txt` manifest. The BaseApplications cross-check ensures we never deduplicate a file the MSI does not actually deploy at the install root, which would otherwise leave both copies missing post-install. The manifest is written as UTF-8 without BOM (via `[System.IO.File]::WriteAllLines` with `UTF8Encoding($false)`) so its encoding is identical regardless of the build host's PowerShell version. This step produces the **MSI download-size win** (~97 MB smaller cab; LZX:21 was already deduplicating most byte-identical content automatically inside the cab). **Install-time** (`CreateWinAppSDKHardlinksCA` custom action): - Reads `hardlinks.txt` after `InstallFiles` as a raw byte stream and converts each line to a `std::wstring` via `MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, ...)`. Avoids `std::wifstream`'s ANSI-codepage codecvt so non-ASCII paths can never be silently mangled. - For each entry, computes `(installDir / fileName).lexically_normal()` and `(winui3Dir / fileName).lexically_normal()`, then verifies via `std::mismatch` that each resolved path is still rooted at its respective folder. Manifest entries containing `..`, absolute paths, or alternate-stream syntax are logged and skipped. - Materialises each validated entry from `<install>\<name>` into `<install>\WinUI3Apps\<name>` via `fs::copy_file` (overwrite_existing). - Reports the per-file copy / failure counts to the install log. If every entry failed (`created == 0 && failed > 0`), the CA escalates to `E_FAIL` so the install does not silently succeed with an unusable WinUI3Apps tree. `DeleteWinAppSDKHardlinksCA` removes the materialised copies before `RemoveFiles` on uninstall, using the same UTF-8 reader and per-entry containment check. **WiX sequencing**: `CreateWinAppSDKHardlinks` runs `After="InstallFiles"` with `Condition="NOT Installed OR WIX_UPGRADE_DETECTED OR REINSTALL"` so a `msiexec /fa` repair refreshes the deduplicated copies (otherwise `RemoveFiles` would orphan them). #### Why copy and not hard-link A hard-linked variant of this CA was originally proposed but caused a Monaco preview-handler regression. Hard-links share an NTFS inode (and therefore one DACL) between `<install>\<file>` and `<install>\WinUI3Apps\<file>`. The MSIX sparse-package registrations for PowerRename / ImageResizer / FileLocksmith / NewPlus run after the dedup CA and propagate the `WinUI3Apps` parent's rich DACL (Capability SID, 5× Package SIDs, 5× conditional SYSAPPID ACE, RC SID) onto the shared inode. The root path then also exposes the rich DACL, which trips a kernel "stricter access evaluation" path that blocks the LOW-IL `prevhost.exe` from `LoadLibrary`-ing `hostfxr.dll` (and the rest of the .NET runtime), turning the Monaco preview pane blank for `.json` / `.md` / `.cs` / `.xaml` / `.svg` / `.xml` files. `fs::copy_file` creates a **fresh inode** for the WinUI3Apps copy. The root inode keeps its simple DACL (`SY:F + BA:F + owner:F` + inherited `BU:RX`) so LOW-IL `prevhost.exe` can still load it — Monaco preview works. The WinUI3Apps copy inherits the WinUI3Apps parent's rich DACL via normal NTFS inheritance (matches 0.99.1 behaviour exactly) — MSIX context-menu shells continue to work. #### Trade-off | Metric | Hard-link variant (rejected) | This PR (file copy) | 0.99.1 (no dedup) | |---|---|---|---| | MSI size | ~296 MB | ~296 MB | ~393 MB | | On-disk after install | ~2,475 MB | ~2,772 MB | ~2,772 MB | | DACL contamination risk | YES (broke Monaco) | NO | NO | The on-disk savings (~297 MB) are given up in exchange for eliminating the DACL contamination risk; the **installer download savings (~97 MB)** are preserved by the build-time WiX/cab dedup. #### Edge cases handled - Empty duplicate list: `hardlinks.txt` always written, CA handles empty. - All files duplicated: `Generate-FileComponents` returns early for empty list. - File stripped from BaseApplications by an earlier build step: BaseApplications cross-check skips it during dedup so neither copy goes missing. - Manifest entry escapes install root (`..`, absolute path): rejected per-entry, install continues. - Manifest line is non-UTF-8: rejected per-entry, install continues. - Source missing at install time: per-entry skip, install continues. - All copies fail: install aborts loudly via `E_FAIL` (catastrophic-case escalation). - Upgrade or `msiexec /fa` repair: CA fires (`NOT Installed OR WIX_UPGRADE_DETECTED OR REINSTALL`). **MSI repair risk**: Burn bundle uses `SuppressRepair=yes` and `MajorUpgrade` (full uninstall + reinstall) for all version upgrades, so the standard upgrade path is unaffected. The `OR REINSTALL` clause covers power users running `msiexec /fa` directly. ## PR Checklist - [x] **Communication:** Discussed approach via PRs #46866, #47177, #46745 - [ ] **Tests:** Installer infrastructure only — no runtime behaviour changes - [ ] **Localization:** N/A - [ ] **Dev docs:** N/A - [ ] **New binaries:** N/A ## Detailed Description of the Pull Request / Additional comments Based on the approach from PR #46745 by @yeelam-gordon, rebased onto latest main and switched from hard-links to file copies after the DACL contamination root cause was identified. Hardening (UTF-8 read, path containment, catastrophic-case escalation, REINSTALL repair, BaseApplications-filtered dedup) added in response to review feedback. These changes are purely build/installer infrastructure — no runtime behaviour changes to any PowerToys module. ## Validation Steps Performed Validated on a 0.99.4 / 0.99.5 local install (per-user `%LocalAppData%\PowerToys`): - ✅ `dumpbin /dependents` across the installed PowerToys tree confirmed zero binaries import `mfc140*`, `mfcm140*`, `vcamp140*`, or `vcomp140*` — the cleanup target removes ~11 MB of genuinely unused VC runtime DLLs. - ✅ `System.Data.SqlClient` has zero call-sites in PowerToys source. - ✅ Local installer build produces a 296 MB MSI (down from 393 MB pre-dedup, ~97 MB cab savings purely from the build-time WiX dedup). - ✅ MSI table inspection (`wix msi decompile`) confirms the deferred CAs are present (`CreateWinAppSDKHardlinks`, `DeleteWinAppSDKHardlinks`) and the `hardlinks.txt` File row is registered. - ✅ MSI table inspection confirms .NET runtime DLLs (`hostfxr.dll`, `coreclr.dll`, `hostpolicy.dll`, `clretwrc.dll`, `Accessibility.dll`, `backup_restore_settings.json`) appear ONLY in `BaseApplicationsFiles_File_*`, NOT in `WinUI3ApplicationsFiles_File_*` — proving the build-time dedup worked. - ✅ Post-install verification: deduplicated files materialised at both root and WinUI3Apps with byte-identical SHA256 hashes, and `fsutil hardlink list` returns link-count == 1 for each — proving the install-time copy approach worked, not hard-link. - ✅ DACL on root .NET runtime DLLs is clean: no Package SID, no Capability SID, no SYSAPPID conditional ACE, no `ALL APPLICATION PACKAGES` ACE — Monaco preview load path is safe. - ✅ DACL on WinUI3Apps copies has the rich MSIX inheritance — context-menu shells continue to work (matches 0.99.1). - ✅ All four MSIX sparse packages (PowerRename, ImageResizer, FileLocksmith, NewPlus) registered after install. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
154 lines
12 KiB
XML
154 lines
12 KiB
XML
<Project>
|
|
<PropertyGroup>
|
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
|
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
|
|
<MSTestVersion>3.8.3</MSTestVersion>
|
|
</PropertyGroup>
|
|
<ItemGroup>
|
|
<PackageVersion Include="AdaptiveCards.ObjectModel.WinUI3" Version="2.0.0-beta" />
|
|
<PackageVersion Include="AdaptiveCards.Rendering.WinUI3" Version="2.1.0-beta" />
|
|
<PackageVersion Include="AdaptiveCards.Templating" Version="2.0.5" />
|
|
<PackageVersion Include="boost" Version="1.87.0" TargetFramework="native" />
|
|
<PackageVersion Include="boost_regex-vc143" Version="1.87.0" TargetFramework="native" />
|
|
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.OpacityMaskView" Version="0.1.251101-build.2372" />
|
|
<PackageVersion Include="Microsoft.Bot.AdaptiveExpressions.Core" Version="4.23.0" />
|
|
<PackageVersion Include="Appium.WebDriver" Version="4.4.5" />
|
|
<PackageVersion Include="CoenM.ImageSharp.ImageHash" Version="1.3.6" />
|
|
<!-- Pin the SixLabors.ImageSharp version (a transitive dependency of CoenM.ImageSharp.ImageHash) to restore functionality and apply patches. -->
|
|
<PackageVersion Include="SixLabors.ImageSharp" Version="2.1.12" />
|
|
<PackageVersion Include="CommunityToolkit.Common" Version="8.4.0" />
|
|
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Animations" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Collections" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Primitives" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Segmented" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Controls.Sizers" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Converters" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.Extensions" Version="8.2.251219" />
|
|
<PackageVersion Include="CommunityToolkit.WinUI.UI.Controls.DataGrid" Version="7.1.2" />
|
|
<PackageVersion Include="CommunityToolkit.Labs.WinUI.Controls.MarkdownTextBlock" Version="0.1.260116-build.2514" />
|
|
<PackageVersion Include="ControlzEx" Version="6.0.0" />
|
|
<PackageVersion Include="HelixToolkit" Version="2.24.0" />
|
|
<PackageVersion Include="HelixToolkit.Core.Wpf" Version="2.24.0" />
|
|
<PackageVersion Include="HtmlAgilityPack" Version="1.12.3" />
|
|
<PackageVersion Include="hyjiacan.pinyin4net" Version="4.1.1" />
|
|
<PackageVersion Include="Interop.Microsoft.Office.Interop.OneNote" Version="1.1.0.2" />
|
|
<PackageVersion Include="LazyCache" Version="2.4.0" />
|
|
<PackageVersion Include="Mages" Version="3.0.0" />
|
|
<PackageVersion Include="Markdig.Signed" Version="0.34.0" />
|
|
<!-- Including MessagePack to force version, since it's used by StreamJsonRpc but contains vulnerabilities. After StreamJsonRpc updates the version of MessagePack, we can upgrade StreamJsonRpc instead. -->
|
|
<PackageVersion Include="MessagePack" Version="3.1.3" />
|
|
<PackageVersion Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.102" />
|
|
<PackageVersion Include="Microsoft.CommandPalette.Extensions" Version="0.9.260303001" />
|
|
<PackageVersion Include="Microsoft.Data.Sqlite" Version="10.0.7" />
|
|
<!-- Including Microsoft.Bcl.AsyncInterfaces to force version, since it's used by Microsoft.SemanticKernel. -->
|
|
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
|
|
<PackageVersion Include="Microsoft.Windows.CppWinRT" Version="2.0.250303.1" />
|
|
<PackageVersion Include="Microsoft.Diagnostics.Tracing.TraceEvent" Version="3.1.16" />
|
|
<PackageVersion Include="Microsoft.Extensions.AI" Version="9.9.1" />
|
|
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="9.9.1-preview.1.25474.6" />
|
|
<PackageVersion Include="Microsoft.Extensions.Caching.Abstractions" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Extensions.Logging" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Extensions.Hosting.WindowsServices" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.AI.Foundry.Local" Version="0.3.0" />
|
|
<PackageVersion Include="Microsoft.SemanticKernel" Version="1.66.0" />
|
|
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.OpenAI" Version="1.66.0" />
|
|
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.AzureAIInference" Version="1.66.0-beta" />
|
|
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Google" Version="1.66.0-alpha" />
|
|
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.MistralAI" Version="1.66.0-alpha" />
|
|
<PackageVersion Include="Microsoft.SemanticKernel.Connectors.Ollama" Version="1.66.0-alpha" />
|
|
<PackageVersion Include="Microsoft.Toolkit.Uwp.Notifications" Version="7.1.2" />
|
|
<PackageVersion Include="Microsoft.Web.WebView2" Version="1.0.3719.77" />
|
|
<!-- Package Microsoft.Win32.SystemEvents added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Drawing.Common but the 8.0.1 version wasn't published to nuget. -->
|
|
<PackageVersion Include="Microsoft.Win32.SystemEvents" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.10.340" />
|
|
<PackageVersion Include="Microsoft.Windows.Compatibility" Version="10.0.7" />
|
|
<PackageVersion Include="Microsoft.Windows.CsWin32" Version="0.3.183" />
|
|
<!-- CsWinRT version needs to be set to have a WinRT.Runtime.dll at the same version contained inside the NET SDK we're currently building on CI. -->
|
|
<!--
|
|
TODO: in Common.Dotnet.CsWinRT.props, on upgrade, verify RemoveCsWinRTPackageAnalyzer is no longer needed.
|
|
This is present due to a bug in CsWinRT where WPF projects cause the analyzer to fail.
|
|
-->
|
|
<PackageVersion Include="Microsoft.Windows.CsWinRT" Version="2.2.0" />
|
|
<PackageVersion Include="Microsoft.Windows.ImplementationLibrary" Version="1.0.250325.1"/>
|
|
<PackageVersion Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.6901" />
|
|
<PackageVersion Include="Microsoft.WindowsAppSDK" Version="2.0.1" />
|
|
<PackageVersion Include="Microsoft.WindowsAppSDK.Foundation" Version="2.0.20" />
|
|
<PackageVersion Include="Microsoft.WindowsAppSDK.AI" Version="2.0.185" />
|
|
<PackageVersion Include="Microsoft.WindowsAppSDK.Runtime" Version="2.0.1" />
|
|
<PackageVersion Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="2.0.9" />
|
|
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
|
<PackageVersion Include="ModernWpfUI" Version="0.9.4" />
|
|
<!-- Moq to stay below v4.20 due to behavior change. need to be sure fixed -->
|
|
<PackageVersion Include="Moq" Version="4.18.4" />
|
|
<PackageVersion Include="MSTest" Version="$(MSTestVersion)" />
|
|
<PackageVersion Include="MSTest.TestFramework" Version="$(MSTestVersion)" />
|
|
<PackageVersion Include="NJsonSchema" Version="11.4.0" />
|
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
|
<PackageVersion Include="NLog" Version="5.2.8" />
|
|
<PackageVersion Include="NLog.Extensions.Logging" Version="5.3.8" />
|
|
<PackageVersion Include="NLog.Schema" Version="5.2.8" />
|
|
<PackageVersion Include="OpenAI" Version="2.5.0" />
|
|
<PackageVersion Include="ReverseMarkdown" Version="4.1.0" />
|
|
<PackageVersion Include="RtfPipe" Version="2.0.7677.4303" />
|
|
<PackageVersion Include="ScipBe.Common.Office.OneNote" Version="3.0.1" />
|
|
<PackageVersion Include="SharpCompress" Version="0.37.2" />
|
|
<PackageVersion Include="Shmuelie.WinRTServer" Version="2.1.1" />
|
|
<!-- Don't update SkiaSharp.Views.WinUI to version 3.* branch as this brakes the HexBox control in Registry Preview. -->
|
|
<PackageVersion Include="SkiaSharp.Views.WinUI" Version="2.88.9" />
|
|
<PackageVersion Include="StreamJsonRpc" Version="2.21.69" />
|
|
<PackageVersion Include="StyleCop.Analyzers" Version="1.2.0-beta.556" />
|
|
<!-- Package System.CodeDom added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Management but the 8.0.1 version wasn't published to nuget. -->
|
|
<PackageVersion Include="System.CodeDom" Version="10.0.7" />
|
|
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
|
|
<PackageVersion Include="System.ComponentModel.Composition" Version="10.0.7" />
|
|
<PackageVersion Include="System.Configuration.ConfigurationManager" Version="10.0.7" />
|
|
<PackageVersion Include="System.Data.OleDb" Version="10.0.7" />
|
|
<!-- Package System.Diagnostics.EventLog added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.1. This is a dependency of System.Data.OleDb but the 8.0.1 version wasn't published to nuget. -->
|
|
<PackageVersion Include="System.Diagnostics.EventLog" Version="10.0.7" />
|
|
<!-- Package System.Diagnostics.PerformanceCounter added as a hack for being able to exclude the runtime assets so they don't conflict with 8.0.11. -->
|
|
<PackageVersion Include="System.Diagnostics.PerformanceCounter" Version="10.0.7" />
|
|
<PackageVersion Include="System.ClientModel" Version="1.7.0" />
|
|
<PackageVersion Include="System.Drawing.Common" Version="10.0.7" />
|
|
<PackageVersion Include="System.IO.Abstractions" Version="22.0.13" />
|
|
<PackageVersion Include="System.IO.Abstractions.TestingHelpers" Version="22.0.13" />
|
|
<PackageVersion Include="System.Management" Version="10.0.7" />
|
|
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
|
|
<PackageVersion Include="System.Numerics.Tensors" Version="9.0.11" />
|
|
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
|
|
<PackageVersion Include="System.Reactive" Version="6.0.1" />
|
|
<PackageVersion Include="System.Runtime.Caching" Version="10.0.7" />
|
|
<PackageVersion Include="System.ServiceProcess.ServiceController" Version="10.0.7" />
|
|
<PackageVersion Include="System.Text.Encoding.CodePages" Version="10.0.7" />
|
|
<PackageVersion Include="System.Text.Json" Version="10.0.7" />
|
|
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
|
|
<PackageVersion Include="ToolGood.Words.Pinyin" Version="3.1.0.3" />
|
|
<PackageVersion Include="UnicodeInformation" Version="2.6.0" />
|
|
<PackageVersion Include="UnitsNet" Version="5.56.0" />
|
|
<PackageVersion Include="UTF.Unknown" Version="2.6.0" />
|
|
<PackageVersion Include="WinUIEx" Version="2.8.0" />
|
|
<PackageVersion Include="WmiLight" Version="6.14.0" />
|
|
<PackageVersion Include="WPF-UI" Version="3.0.5" />
|
|
<PackageVersion Include="WyHash" Version="1.0.5" />
|
|
<PackageVersion Include="WixToolset.Heat" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.Firewall.wixext" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.Util.wixext" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.UI.wixext" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.NetFx.wixext" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.Bal.wixext" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.BootstrapperApplicationApi" Version="5.0.2" />
|
|
<PackageVersion Include="WixToolset.WixStandardBootstrapperApplicationFunctionApi" Version="5.0.2" />
|
|
</ItemGroup>
|
|
<ItemGroup Condition="'$(IsExperimentationLive)'!=''">
|
|
<!-- Additional dependencies used by experimentation -->
|
|
<PackageVersion Include="Microsoft.VariantAssignment.Client" Version="2.4.17140001" />
|
|
<PackageVersion Include="Microsoft.VariantAssignment.Contract" Version="3.0.16990001" />
|
|
</ItemGroup>
|
|
</Project>
|