Merge remote-tracking branch 'origin/dev/vanzue/fix-local-installer-build' into dev/vanzue/cmdpal-pt

This commit is contained in:
Kai Tao
2025-12-08 11:24:09 +08:00
2 changed files with 79 additions and 25 deletions

View File

@@ -3,14 +3,7 @@
Build and package PowerToys (CmdPal and installer) for a specific platform and configuration LOCALLY.
.DESCRIPTION
This script automates the end-to-end build and packaging process for PowerToys, including:
- Restoring and building all necessary solutions (CmdPal, BugReportTool, etc.)
- Cleaning up old output
- Signing generated .msix packages
- Building the WiX v5 (VNext) MSI and bootstrapper installers
It is designed to work in local development.
The cert used to sign the packages is generated by
Builds and packages PowerToys (CmdPal and installer) locally. Handles solution build, signing, and WiX installer generation.
.PARAMETER Platform
Specifies the target platform for the build (e.g., 'arm64', 'x64'). Default is 'x64'.
@@ -45,11 +38,25 @@ Runs the pipeline for x64 Release with machine-wide installer.
#>
param (
[string]$Platform = '',
[string]$Platform = 'x64',
[string]$Configuration = 'Release',
[string]$PerUser = 'true'
[string]$PerUser = 'true',
[switch]$Clean,
[switch]$SkipBuild,
[switch]$Help
)
if ($Help) {
Write-Host "Usage: .\build-installer.ps1 [-Platform <x64|arm64>] [-Configuration <Release|Debug>] [-PerUser <true|false>] [-Clean] [-SkipBuild]"
Write-Host " -Platform Target platform (default: auto-detect or x64)"
Write-Host " -Configuration Build configuration (default: Release)"
Write-Host " -PerUser Build per-user installer (default: true)"
Write-Host " -Clean Clean output directories before building"
Write-Host " -SkipBuild Skip building the main solution and tools (assumes they are already built)"
Write-Host " -Help Show this help message"
exit 0
}
# Ensure helpers are available
. "$PSScriptRoot\build-common.ps1"
@@ -94,15 +101,37 @@ Write-Host ("[PIPELINE] Start | Platform={0} Configuration={1} PerUser={2}" -f $
Write-Host ''
$cmdpalOutputPath = Join-Path $repoRoot "$Platform\$Configuration\WinUI3Apps\CmdPal"
$buildOutputPath = Join-Path $repoRoot "$Platform\$Configuration"
if (Test-Path $cmdpalOutputPath) {
Write-Host "[CLEAN] Removing previous output: $cmdpalOutputPath"
Remove-Item $cmdpalOutputPath -Recurse -Force -ErrorAction Ignore
if ($Clean) {
if (Test-Path $cmdpalOutputPath) {
Write-Host "[CLEAN] Removing previous output: $cmdpalOutputPath"
Remove-Item $cmdpalOutputPath -Recurse -Force -ErrorAction Ignore
}
if (Test-Path $buildOutputPath) {
Write-Host "[CLEAN] Removing previous build output: $buildOutputPath"
Remove-Item $buildOutputPath -Recurse -Force -ErrorAction Ignore
}
Write-Host "[CLEAN] Cleaning all build artifacts (git clean -Xfd)..."
Push-Location $repoRoot
try {
git clean -Xfd | Out-Null
} catch {
Write-Warning "[CLEAN] git clean failed: $_"
} finally {
Pop-Location
}
Write-Host "[CLEAN] Cleaning solution (msbuild /t:Clean)..."
RunMSBuild 'PowerToys.slnx' '/t:Clean' $Platform $Configuration
}
$commonArgs = '/p:CIBuild=true'
$commonArgs = '/p:CIBuild=true /p:IsPipeline=true'
# No local projects found (or continuing) - build full solution and tools
RestoreThenBuild 'PowerToys.slnx' $commonArgs $Platform $Configuration
if (-not $SkipBuild) {
RestoreThenBuild 'PowerToys.slnx' $commonArgs $Platform $Configuration
}
$msixSearchRoot = Join-Path $repoRoot "$Platform\$Configuration"
$msixFiles = Get-ChildItem -Path $msixSearchRoot -Recurse -Filter *.msix |
@@ -130,21 +159,36 @@ if (Test-Path $dscScriptPath) {
Write-Warning "[DSC] DSC manifest generator script not found at: $dscScriptPath"
}
RestoreThenBuild 'tools\BugReportTool\BugReportTool.sln' $commonArgs $Platform $Configuration
RestoreThenBuild 'tools\StylesReportTool\StylesReportTool.sln' $commonArgs $Platform $Configuration
if (-not $SkipBuild) {
RestoreThenBuild 'tools\BugReportTool\BugReportTool.sln' $commonArgs $Platform $Configuration
RestoreThenBuild 'tools\StylesReportTool\StylesReportTool.sln' $commonArgs $Platform $Configuration
}
Write-Host '[CLEAN] installer (keep *.exe)'
Push-Location $repoRoot
try {
git clean -xfd -e '*.exe' -- .\installer\ | Out-Null
} finally {
Pop-Location
if ($Clean) {
Write-Host '[CLEAN] installer (keep *.exe)'
Push-Location $repoRoot
try {
git clean -xfd -e '*.exe' -- .\installer\ | Out-Null
} finally {
Pop-Location
}
}
RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /t:restore /p:RestorePackagesConfig=true" $Platform $Configuration
RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /m /t:PowerToysInstallerVNext /p:PerUser=$PerUser" $Platform $Configuration
# Fix: WiX v5 locally puts the MSI in an 'en-us' subfolder, but the Bootstrapper expects it in the root of UserSetup/MachineSetup.
# We move it up one level to match expectations.
$setupType = if ($PerUser -eq 'true') { 'UserSetup' } else { 'MachineSetup' }
$msiParentDir = Join-Path $repoRoot "installer\PowerToysSetupVNext\$Platform\$Configuration\$setupType"
$msiEnUsDir = Join-Path $msiParentDir "en-us"
if (Test-Path $msiEnUsDir) {
Write-Host "[FIX] Moving MSI files from $msiEnUsDir to $msiParentDir"
Get-ChildItem -Path $msiEnUsDir -Filter *.msi | Move-Item -Destination $msiParentDir -Force
}
RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /m /t:PowerToysBootstrapperVNext /p:PerUser=$PerUser" $Platform $Configuration
Write-Host '[PIPELINE] Completed'

View File

@@ -61,8 +61,18 @@ function ImportAndVerifyCertificate {
try {
$null = Import-Certificate -FilePath $cerPath -CertStoreLocation $storePath -ErrorAction Stop
} catch {
Write-Warning "Failed to import certificate to $storePath : $_"
return $false
if ($_.Exception.Message -match "Access is denied" -or $_.Exception.InnerException.Message -match "Access is denied") {
Write-Warning "Access denied to $storePath. Attempting to import with admin privileges..."
try {
Start-Process powershell -ArgumentList "-NoProfile", "-Command", "& { Import-Certificate -FilePath '$cerPath' -CertStoreLocation '$storePath' }" -Verb RunAs -Wait
} catch {
Write-Warning "Failed to request admin privileges: $_"
return $false
}
} else {
Write-Warning "Failed to import certificate to $storePath : $_"
return $false
}
}
$imported = Get-ChildItem -Path $storePath | Where-Object { $_.Thumbprint -eq $thumbprint }