diff --git a/.pipelines/ESRPSigning_core.json b/.pipelines/ESRPSigning_core.json index 5ae6a931cc..4beb999538 100644 --- a/.pipelines/ESRPSigning_core.json +++ b/.pipelines/ESRPSigning_core.json @@ -264,8 +264,8 @@ "Workspaces.ModuleServices.dll", "Microsoft.CommandPalette.Extensions.dll", "Microsoft.CommandPalette.Extensions.Toolkit.dll", - "Microsoft.CmdPal.Ext.PowerToys.dll", - "Microsoft.CmdPal.Ext.PowerToys.exe", + "WinUI3Apps\\Microsoft.CmdPal.Ext.PowerToys.dll", + "WinUI3Apps\\Microsoft.CmdPal.Ext.PowerToys.exe", "*Microsoft.CmdPal.UI_*.msix", "PowerToys.DSC.dll", diff --git a/doc/devdocs/modules/cmdpal/powertoys-extension-local-development.md b/doc/devdocs/modules/cmdpal/powertoys-extension-local-development.md index 506adfb61e..f933b7e6db 100644 --- a/doc/devdocs/modules/cmdpal/powertoys-extension-local-development.md +++ b/doc/devdocs/modules/cmdpal/powertoys-extension-local-development.md @@ -2,7 +2,7 @@ This guide is for iterating on `src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj`. -The extension is registered through the shared sparse package defined in `src/PackageIdentity/AppxManifest.xml`. That manifest declares `Microsoft.CmdPal.Ext.PowerToys.exe` at the sparse package root, so the sparse package and the extension must be built for the same platform and configuration, for example `x64\Debug`. +The extension is registered through the shared sparse package defined in `src/PackageIdentity/AppxManifest.xml`. That manifest declares `Microsoft.CmdPal.Ext.PowerToys.exe` relative to the sparse package's ExternalLocation (`WinUI3Apps\` subfolder), so the sparse package and the extension must be built for the same platform and configuration, for example `x64\Debug`. ## Local development loop @@ -30,12 +30,12 @@ The extension is registered through the shared sparse package defined in `src/Pa The command will look like this: ```powershell - Add-AppxPackage -Path "\\\PowerToysSparse.msix" -ExternalLocation "\\" + Add-AppxPackage -Path "\\\PowerToysSparse.msix" -ExternalLocation "\\\WinUI3Apps" ``` 4. Build `src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj` in the same platform and configuration. - This project writes `Microsoft.CmdPal.Ext.PowerToys.exe` directly into the sparse package root, such as `x64\Debug` or `ARM64\Debug`. That matches the `Executable="Microsoft.CmdPal.Ext.PowerToys.exe"` entry in `src/PackageIdentity/AppxManifest.xml`. + This project writes `Microsoft.CmdPal.Ext.PowerToys.exe` into the `WinUI3Apps\` subfolder of the output root, such as `x64\Debug\WinUI3Apps` or `ARM64\Debug\WinUI3Apps`. That matches the `Executable="Microsoft.CmdPal.Ext.PowerToys.exe"` entry in `src/PackageIdentity/AppxManifest.xml` resolved relative to the sparse package's ExternalLocation. 5. Restart Command Palette. diff --git a/installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp b/installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp index bb491e4588..890a9fdf6e 100644 --- a/installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp +++ b/installer/PowerToysSetupCustomActionsVNext/CustomAction.cpp @@ -639,7 +639,7 @@ UINT __stdcall InstallPackageIdentityMSIXCA(MSIHANDLE hInstall) try { - std::wstring externalLocation = installFolderPath; // External content location (PowerToys install folder) + std::wstring externalLocation = installFolderPath + L"WinUI3Apps\\"; // External content location (WinUI3Apps subfolder to isolate DACL changes from preview handler DLLs) Uri externalUri{ externalLocation }; // External location URI for sparse package content Uri packageUri{ msixPath }; // The MSIX file URI diff --git a/installer/PowerToysSetupVNext/BaseApplications.wxs b/installer/PowerToysSetupVNext/BaseApplications.wxs index 57a9c71637..4de71b10df 100644 --- a/installer/PowerToysSetupVNext/BaseApplications.wxs +++ b/installer/PowerToysSetupVNext/BaseApplications.wxs @@ -11,7 +11,7 @@ - + diff --git a/installer/PowerToysSetupVNext/KeyboardManager.wxs b/installer/PowerToysSetupVNext/KeyboardManager.wxs index d6948d6598..12efd1b2be 100644 --- a/installer/PowerToysSetupVNext/KeyboardManager.wxs +++ b/installer/PowerToysSetupVNext/KeyboardManager.wxs @@ -4,11 +4,11 @@ - + - + diff --git a/installer/PowerToysSetupVNext/Resources.wxs b/installer/PowerToysSetupVNext/Resources.wxs index 808883920b..f781f336b9 100644 --- a/installer/PowerToysSetupVNext/Resources.wxs +++ b/installer/PowerToysSetupVNext/Resources.wxs @@ -9,7 +9,7 @@ - + @@ -361,11 +361,11 @@ - + - + @@ -433,6 +433,7 @@ + diff --git a/installer/PowerToysSetupVNext/generateAllFileComponents.ps1 b/installer/PowerToysSetupVNext/generateAllFileComponents.ps1 index ea5d143941..048f587def 100644 --- a/installer/PowerToysSetupVNext/generateAllFileComponents.ps1 +++ b/installer/PowerToysSetupVNext/generateAllFileComponents.ps1 @@ -191,7 +191,7 @@ Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFil Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs #KeyboardManager -Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsFiles -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\KeyboardManager" +Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsFiles -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\KeyboardManager" Generate-FileList -fileDepsJson "" -fileListName KeyboardManagerAssetsWinUI3Files -wxsFilePath $PSScriptRoot\KeyboardManager.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\KeyboardManagerEditor" Generate-FileComponents -fileListName "KeyboardManagerAssetsFiles" -wxsFilePath $PSScriptRoot\KeyboardManager.wxs Generate-FileComponents -fileListName "KeyboardManagerAssetsWinUI3Files" -wxsFilePath $PSScriptRoot\KeyboardManager.wxs diff --git a/src/PackageIdentity/AppxManifest.xml b/src/PackageIdentity/AppxManifest.xml index 502cc33ff0..edfa0af5b7 100644 --- a/src/PackageIdentity/AppxManifest.xml +++ b/src/PackageIdentity/AppxManifest.xml @@ -38,17 +38,7 @@ - - - - - + - + The MSIX contains only metadata. When the package is registered you must point `-ExternalLocation` to the output folder that hosts the Win32 binaries (for example `x64\Release`). +> The MSIX contains only metadata. When the package is registered you must point `-ExternalLocation` to the `WinUI3Apps` subfolder of the output folder that hosts the Win32 binaries (for example `x64\Release\WinUI3Apps`). This isolates the DACL changes that MSIX registration applies on Windows 23H2/24H2 to the `WinUI3Apps` folder, keeping the root install folder clean for preview handler DLLs. ## Building the sparse package locally @@ -53,16 +53,17 @@ After `PowerToysSparse.msix` is generated: # First time registration $repoRoot = "C:/git/PowerToys" $outputRoot = Join-Path $repoRoot "x64/Release" -Add-AppxPackage -Path (Join-Path $outputRoot "PowerToysSparse.msix") -ExternalLocation $outputRoot +$externalLocation = Join-Path $outputRoot "WinUI3Apps" +Add-AppxPackage -Path (Join-Path $outputRoot "PowerToysSparse.msix") -ExternalLocation $externalLocation # Re-register after manifest tweaks only -Add-AppxPackage -Register (Join-Path $repoRoot "src/PackageIdentity/AppxManifest.xml") -ExternalLocation $outputRoot -ForceApplicationShutdown +Add-AppxPackage -Register (Join-Path $repoRoot "src/PackageIdentity/AppxManifest.xml") -ExternalLocation $externalLocation -ForceApplicationShutdown # Remove the sparse identity Get-AppxPackage -Name Microsoft.PowerToys.SparseApp | Remove-AppxPackage ``` -`-ExternalLocation` should match the output folder that contains the Win32 executables declared in the manifest. Re-run registration whenever the manifest or executable layout changes. +`-ExternalLocation` should match the `WinUI3Apps` subfolder that contains the Win32 executables declared in the manifest. Re-run registration whenever the manifest or executable layout changes. ## CI-specific guidance @@ -72,7 +73,7 @@ Get-AppxPackage -Name Microsoft.PowerToys.SparseApp | Remove-AppxPackage ## Consuming the identity from other components -1. Add a new `` entry inside `src/PackageIdentity/AppxManifest.xml`. Use a unique `Id` (for example `PowerToys.MyModuleUI`) and set `Executable` to the Win32 binary relative to the `-ExternalLocation` root. +1. Add a new `` entry inside `src/PackageIdentity/AppxManifest.xml`. Use a unique `Id` (for example `PowerToys.MyModuleUI`) and set `Executable` to the Win32 binary relative to the `-ExternalLocation` (`WinUI3Apps` subfolder). 2. Ensure the binary is copied into the platform/configuration output folder (`x64\Release`, `ARM64\Debug`, etc.) so the sparse package can locate it. 3. Embed a sparse identity manifest in the Win32 binary so it binds to the MSIX identity at runtime. The manifest must declare an `` element with `packageName="Microsoft.PowerToys.SparseApp"`, `applicationId` matching the ``, and a `publisher` that matches the sparse package. Keep the manifest’s publisher in sync with `src/PackageIdentity/.user/PowerToysSparse.publisher.txt` (emitted by `BuildSparsePackage.ps1`). See `src/modules/imageresizer/ui/ImageResizerUI.csproj` for an example that points `ApplicationManifest` to `ImageResizerUI.dev.manifest` for local builds and switches to `ImageResizerUI.prod.manifest` when `$(CIBuild)` is `true`. 4. Register or re-register the sparse package so Windows learns about the new application Id. diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/PowerToysResourcesHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/PowerToysResourcesHelper.cs index bdceae9058..f1ea3002d9 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/PowerToysResourcesHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Helpers/PowerToysResourcesHelper.cs @@ -10,7 +10,7 @@ namespace PowerToysExtension.Helpers; internal static class PowerToysResourcesHelper { private const string AssetsRoot = "Assets\\"; - private const string SettingsIconRoot = "WinUI3Apps\\Assets\\Settings\\Icons\\"; + private const string SettingsIconRoot = "Assets\\Settings\\Icons\\"; internal static IconInfo IconFromSettingsIcon(string fileName) => IconHelpers.FromRelativePath($"{SettingsIconRoot}{fileName}"); diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj index 1e8fd040a0..03617e9748 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.PowerToys/Microsoft.CmdPal.Ext.PowerToys.csproj @@ -12,7 +12,7 @@ false None false - $(SolutionDir)$(Platform)\$(Configuration)\ + $(SolutionDir)$(Platform)\$(Configuration)\WinUI3Apps\ false false enable @@ -27,11 +27,11 @@ - + PreserveNewest - + PreserveNewest