mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-16 03:37:59 +01:00
[Installer] Upgrade the installer from WiX3 to WiX5 (#40877)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Background: The current PowerToys installer is built using Wix3, which has now been deprecated. To improve security, service quality, and community support, we’re upgrading the installer to Wix5. Implementation: Created Wix5-based projects(PowerToysSetupVext and PowerToysSetupCustomActionsVNext) within the installer while retaining the existing Wix3 project. Both versions are built to generate separate installation packages. The Wix3-related code will be removed after successful release testing confirms no issues. Special case: Wix5 has removed the property for 'ShowFilesInUse'. Now, whenever a file is in use during installation, a FilesInUse pop-upwill automatically appear asking for the next step. To ensure this doesn't interfere with scenarios that require silent installation (e.g. Winget method), we’ve handled it using the bafunction approach. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: #xxx - [ ] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [ ] **Tests:** Added/updated and all pass - [ ] **Localization:** All end-user-facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed --------- Co-authored-by: Jerry Xu <n.xu@outlook.com> Co-authored-by: Kai Tao <69313318+vanzue@users.noreply.github.com> Co-authored-by: leileizhang <leilzh@microsoft.com> Co-authored-by: Kai Tao (from Dev Box) <kaitao@microsoft.com> Co-authored-by: vanzue <vanzue@outlook.com>
This commit is contained in:
831
tools/Verification scripts/verify-installation-script.ps1
Normal file
831
tools/Verification scripts/verify-installation-script.ps1
Normal file
@@ -0,0 +1,831 @@
|
||||
#Requires -Version 5.1
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Verifies a PowerToys installation by checking all components, registry entries, files, and custom logic.
|
||||
|
||||
.DESCRIPTION
|
||||
This script comprehensively verifies a PowerToys installation by checking:
|
||||
- Registry entries for both per-machine and per-user installations
|
||||
- File and folder structure integrity
|
||||
- Module registration and functionality
|
||||
- WiX installer logic verification
|
||||
- Custom action results
|
||||
- DSC module installation
|
||||
- Command Palette packages
|
||||
|
||||
.PARAMETER InstallScope
|
||||
Specifies the installation scope to verify. Valid values are 'PerMachine' or 'PerUser'.
|
||||
Default is 'PerMachine'.
|
||||
|
||||
.PARAMETER InstallPath
|
||||
Optional. Specifies a custom installation path to verify. If not provided, the script will
|
||||
detect the installation path from the registry.
|
||||
|
||||
.EXAMPLE
|
||||
.\verify-installation-script.ps1 -InstallScope PerMachine
|
||||
|
||||
.EXAMPLE
|
||||
.\verify-installation-script.ps1 -InstallScope PerUser
|
||||
|
||||
.NOTES
|
||||
Author: PowerToys Team
|
||||
Requires: PowerShell 5.1 or later
|
||||
Requires: Administrative privileges for per-machine verification
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $false)]
|
||||
[ValidateSet('PerMachine', 'PerUser')]
|
||||
[string]$InstallScope = 'PerMachine',
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$InstallPath
|
||||
)
|
||||
|
||||
# Initialize results tracking
|
||||
$script:Results = @{
|
||||
Summary = @{
|
||||
TotalChecks = 0
|
||||
PassedChecks = 0
|
||||
FailedChecks = 0
|
||||
WarningChecks = 0
|
||||
OverallStatus = "Unknown"
|
||||
}
|
||||
Details = @{}
|
||||
Timestamp = Get-Date
|
||||
Computer = $env:COMPUTERNAME
|
||||
User = $env:USERNAME
|
||||
PowerShellVersion = $PSVersionTable.PSVersion.ToString()
|
||||
}
|
||||
|
||||
# PowerToys constants
|
||||
$PowerToysUpgradeCodePerMachine = "{42B84BF7-5FBF-473B-9C8B-049DC16F7708}"
|
||||
$PowerToysUpgradeCodePerUser = "{D8B559DB-4C98-487A-A33F-50A8EEE42726}"
|
||||
$PowerToysRegistryKeyPerMachine = "HKLM:\SOFTWARE\Classes\PowerToys"
|
||||
$PowerToysRegistryKeyPerUser = "HKCU:\SOFTWARE\Classes\PowerToys"
|
||||
|
||||
# Utility functions
|
||||
function Write-StatusMessage {
|
||||
param(
|
||||
[string]$Message,
|
||||
[ValidateSet('Info', 'Success', 'Warning', 'Error')]
|
||||
[string]$Level = 'Info'
|
||||
)
|
||||
|
||||
$color = switch ($Level) {
|
||||
'Info' { 'White' }
|
||||
'Success' { 'Green' }
|
||||
'Warning' { 'Yellow' }
|
||||
'Error' { 'Red' }
|
||||
}
|
||||
|
||||
$prefix = switch ($Level) {
|
||||
'Info' { '[INFO]' }
|
||||
'Success' { '[PASS]' }
|
||||
'Warning' { '[WARN]' }
|
||||
'Error' { '[FAIL]' }
|
||||
}
|
||||
|
||||
Write-Host "$prefix $Message" -ForegroundColor $color
|
||||
}
|
||||
|
||||
function Add-CheckResult {
|
||||
param(
|
||||
[string]$Category,
|
||||
[string]$CheckName,
|
||||
[string]$Status,
|
||||
[string]$Message,
|
||||
[object]$Details = $null
|
||||
)
|
||||
|
||||
$script:Results.Summary.TotalChecks++
|
||||
|
||||
switch ($Status) {
|
||||
'Pass' { $script:Results.Summary.PassedChecks++ }
|
||||
'Fail' { $script:Results.Summary.FailedChecks++ }
|
||||
'Warning' { $script:Results.Summary.WarningChecks++ }
|
||||
}
|
||||
|
||||
if (-not $script:Results.Details.ContainsKey($Category)) {
|
||||
$script:Results.Details[$Category] = @{}
|
||||
}
|
||||
|
||||
$checkDetails = @{
|
||||
Status = $Status
|
||||
Message = $Message
|
||||
Details = $Details
|
||||
Timestamp = Get-Date
|
||||
}
|
||||
|
||||
$script:Results.Details[$Category][$CheckName] = $checkDetails
|
||||
|
||||
# Always show all checks with their status
|
||||
$level = switch ($Status) {
|
||||
'Pass' { 'Success' }
|
||||
'Fail' { 'Error' }
|
||||
'Warning' { 'Warning' }
|
||||
}
|
||||
Write-StatusMessage "[$Category] $CheckName - $Message" -Level $level
|
||||
}
|
||||
|
||||
function Test-RegistryKey {
|
||||
param(
|
||||
[string]$Path
|
||||
)
|
||||
try {
|
||||
return Test-Path $Path
|
||||
}
|
||||
catch {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Get-RegistryValue {
|
||||
param(
|
||||
[string]$Path,
|
||||
[string]$Name,
|
||||
[object]$DefaultValue = $null
|
||||
)
|
||||
try {
|
||||
$value = Get-ItemProperty -Path $Path -Name $Name -ErrorAction SilentlyContinue
|
||||
return $value.$Name
|
||||
}
|
||||
catch {
|
||||
return $DefaultValue
|
||||
}
|
||||
}
|
||||
|
||||
function Test-PowerToysInstallation {
|
||||
param(
|
||||
[ValidateSet('PerMachine', 'PerUser')]
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
Write-StatusMessage "Verifying PowerToys $Scope installation..." -Level Info
|
||||
|
||||
# Determine registry paths based on scope
|
||||
$registryKey = if ($Scope -eq 'PerMachine') { $PowerToysRegistryKeyPerMachine } else { $PowerToysRegistryKeyPerUser }
|
||||
|
||||
# Check main registry key
|
||||
$mainKeyExists = Test-RegistryKey -Path $registryKey
|
||||
Add-CheckResult -Category "Registry" -CheckName "Main Registry Key ($Scope)" -Status $(if ($mainKeyExists) { 'Pass' } else { 'Fail' }) -Message "Registry key exists: $registryKey"
|
||||
|
||||
if (-not $mainKeyExists) {
|
||||
Add-CheckResult -Category "Installation" -CheckName "Installation Status ($Scope)" -Status 'Fail' -Message "PowerToys $Scope installation not found"
|
||||
return $false
|
||||
}
|
||||
|
||||
# Check install scope value
|
||||
$installScopeValue = Get-RegistryValue -Path $registryKey -Name "InstallScope"
|
||||
$expectedScope = $Scope.ToLower()
|
||||
if ($Scope -eq 'PerMachine') { $expectedScope = 'perMachine' }
|
||||
if ($Scope -eq 'PerUser') { $expectedScope = 'perUser' }
|
||||
|
||||
$scopeCorrect = $installScopeValue -eq $expectedScope
|
||||
Add-CheckResult -Category "Registry" -CheckName "Install Scope Value ($Scope)" -Status $(if ($scopeCorrect) { 'Pass' } else { 'Fail' }) -Message "Install scope: Expected '$expectedScope', Found '$installScopeValue'"
|
||||
|
||||
# Check for uninstall registry entry (this is what makes PowerToys appear in Add/Remove Programs)
|
||||
$uninstallKey = if ($Scope -eq 'PerMachine') {
|
||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||
}
|
||||
else {
|
||||
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||
}
|
||||
|
||||
try {
|
||||
$powerToysEntry = Get-ItemProperty -Path $uninstallKey | Where-Object {
|
||||
$_.DisplayName -like "*PowerToys*"
|
||||
} | Select-Object -First 1
|
||||
|
||||
if ($powerToysEntry) {
|
||||
Add-CheckResult -Category "Registry" -CheckName "Uninstall Registry Entry ($Scope)" -Status 'Pass' -Message "PowerToys uninstall entry found with DisplayName: $($powerToysEntry.DisplayName)"
|
||||
|
||||
# Note: InstallLocation may or may not be set in the uninstall registry
|
||||
# This is normal behavior as PowerToys uses direct file references for system bindings
|
||||
if ($powerToysEntry.InstallLocation) {
|
||||
Add-CheckResult -Category "Registry" -CheckName "Install Location Registry ($Scope)" -Status 'Pass' -Message "InstallLocation found: $($powerToysEntry.InstallLocation)"
|
||||
}
|
||||
# No need to report missing InstallLocation as it's not required
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Registry" -CheckName "Uninstall Registry Entry ($Scope)" -Status 'Fail' -Message "PowerToys uninstall entry not found in Windows uninstall registry"
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Add-CheckResult -Category "Registry" -CheckName "Uninstall Registry Entry ($Scope)" -Status 'Fail' -Message "Failed to read Windows uninstall registry"
|
||||
}
|
||||
|
||||
# Check for installation folder
|
||||
$installFolder = Get-PowerToysInstallPath -Scope $Scope
|
||||
if ($installFolder -and (Test-Path $installFolder)) {
|
||||
Add-CheckResult -Category "Installation" -CheckName "Install Folder ($Scope)" -Status 'Pass' -Message "Installation folder exists: $installFolder"
|
||||
|
||||
# Verify core files
|
||||
Test-CoreFiles -InstallPath $installFolder -Scope $Scope
|
||||
|
||||
# Verify modules
|
||||
Test-ModuleFiles -InstallPath $installFolder -Scope $Scope
|
||||
|
||||
return $true
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Installation" -CheckName "Install Folder ($Scope)" -Status 'Fail' -Message "Installation folder not found or inaccessible: $installFolder"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
function Get-PowerToysInstallPath {
|
||||
param(
|
||||
[ValidateSet('PerMachine', 'PerUser')]
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
if ($InstallPath) {
|
||||
return $InstallPath
|
||||
}
|
||||
|
||||
# Since InstallLocation may not be reliably set in the uninstall registry,
|
||||
# we'll use the default installation paths based on scope
|
||||
if ($Scope -eq 'PerMachine') {
|
||||
$defaultPath = "${env:ProgramFiles}\PowerToys"
|
||||
}
|
||||
else {
|
||||
$defaultPath = "${env:LOCALAPPDATA}\PowerToys"
|
||||
}
|
||||
|
||||
# Verify the path exists before returning it
|
||||
if (Test-Path $defaultPath) {
|
||||
return $defaultPath
|
||||
}
|
||||
|
||||
# If default path doesn't exist, try to get it from uninstall registry as fallback
|
||||
$uninstallKey = if ($Scope -eq 'PerMachine') {
|
||||
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||
}
|
||||
else {
|
||||
"HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||
}
|
||||
|
||||
try {
|
||||
$powerToysEntry = Get-ItemProperty -Path $uninstallKey | Where-Object {
|
||||
$_.DisplayName -like "*PowerToys*"
|
||||
} | Select-Object -First 1
|
||||
|
||||
# Check for InstallLocation first, but it may not exist
|
||||
if ($powerToysEntry -and $powerToysEntry.InstallLocation) {
|
||||
return $powerToysEntry.InstallLocation.TrimEnd('\')
|
||||
}
|
||||
|
||||
# Check for UninstallString as alternative source of install path
|
||||
if ($powerToysEntry -and $powerToysEntry.UninstallString) {
|
||||
# Extract directory from uninstall string like "C:\Program Files\PowerToys\unins000.exe"
|
||||
$uninstallExe = $powerToysEntry.UninstallString.Trim('"')
|
||||
$installDir = Split-Path $uninstallExe -Parent
|
||||
if ($installDir -and (Test-Path $installDir)) {
|
||||
return $installDir
|
||||
}
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# If registry read fails, fall back to null
|
||||
}
|
||||
|
||||
# If we can't determine the install path, return null
|
||||
return $null
|
||||
}
|
||||
|
||||
function Test-CoreFiles {
|
||||
param(
|
||||
[string]$InstallPath,
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
# Essential core files (must exist for basic functionality)
|
||||
$essentialCoreFiles = @(
|
||||
'PowerToys.exe',
|
||||
'PowerToys.ActionRunner.exe',
|
||||
'License.rtf',
|
||||
'Notice.md'
|
||||
)
|
||||
|
||||
# Critical signed PowerToys executable files (from ESRP signing config)
|
||||
$criticalSignedFiles = @(
|
||||
# Main PowerToys components
|
||||
'PowerToys.exe',
|
||||
'PowerToys.ActionRunner.exe',
|
||||
'PowerToys.Update.exe',
|
||||
'PowerToys.BackgroundActivatorDLL.dll',
|
||||
'PowerToys.FilePreviewCommon.dll',
|
||||
'PowerToys.Interop.dll',
|
||||
|
||||
# Common libraries
|
||||
'CalculatorEngineCommon.dll',
|
||||
'PowerToys.ManagedTelemetry.dll',
|
||||
'PowerToys.ManagedCommon.dll',
|
||||
'PowerToys.ManagedCsWin32.dll',
|
||||
'PowerToys.Common.UI.dll',
|
||||
'PowerToys.Settings.UI.Lib.dll',
|
||||
'PowerToys.GPOWrapper.dll',
|
||||
'PowerToys.GPOWrapperProjection.dll',
|
||||
'PowerToys.AllExperiments.dll',
|
||||
|
||||
# Module executables and libraries
|
||||
'PowerToys.AlwaysOnTop.exe',
|
||||
'PowerToys.AlwaysOnTopModuleInterface.dll',
|
||||
'PowerToys.CmdNotFoundModuleInterface.dll',
|
||||
'PowerToys.ColorPicker.dll',
|
||||
'PowerToys.ColorPickerUI.dll',
|
||||
'PowerToys.ColorPickerUI.exe',
|
||||
'PowerToys.CropAndLockModuleInterface.dll',
|
||||
'PowerToys.CropAndLock.exe',
|
||||
'PowerToys.PowerOCRModuleInterface.dll',
|
||||
'PowerToys.PowerOCR.dll',
|
||||
'PowerToys.PowerOCR.exe',
|
||||
'PowerToys.AdvancedPasteModuleInterface.dll',
|
||||
'PowerToys.AwakeModuleInterface.dll',
|
||||
'PowerToys.Awake.exe',
|
||||
'PowerToys.Awake.dll',
|
||||
|
||||
# FancyZones
|
||||
'PowerToys.FancyZonesEditor.exe',
|
||||
'PowerToys.FancyZonesEditor.dll',
|
||||
'PowerToys.FancyZonesEditorCommon.dll',
|
||||
'PowerToys.FancyZonesModuleInterface.dll',
|
||||
'PowerToys.FancyZones.exe',
|
||||
|
||||
# Preview handlers
|
||||
'PowerToys.GcodePreviewHandler.dll',
|
||||
'PowerToys.GcodePreviewHandler.exe',
|
||||
'PowerToys.GcodePreviewHandlerCpp.dll',
|
||||
'PowerToys.GcodeThumbnailProvider.dll',
|
||||
'PowerToys.GcodeThumbnailProvider.exe',
|
||||
'PowerToys.GcodeThumbnailProviderCpp.dll',
|
||||
'PowerToys.BgcodePreviewHandler.dll',
|
||||
'PowerToys.BgcodePreviewHandler.exe',
|
||||
'PowerToys.BgcodePreviewHandlerCpp.dll',
|
||||
'PowerToys.BgcodeThumbnailProvider.dll',
|
||||
'PowerToys.BgcodeThumbnailProvider.exe',
|
||||
'PowerToys.BgcodeThumbnailProviderCpp.dll',
|
||||
'PowerToys.MarkdownPreviewHandler.dll',
|
||||
'PowerToys.MarkdownPreviewHandler.exe',
|
||||
'PowerToys.MarkdownPreviewHandlerCpp.dll',
|
||||
'PowerToys.MonacoPreviewHandler.dll',
|
||||
'PowerToys.MonacoPreviewHandler.exe',
|
||||
'PowerToys.MonacoPreviewHandlerCpp.dll',
|
||||
'PowerToys.PdfPreviewHandler.dll',
|
||||
'PowerToys.PdfPreviewHandler.exe',
|
||||
'PowerToys.PdfPreviewHandlerCpp.dll',
|
||||
'PowerToys.PdfThumbnailProvider.dll',
|
||||
'PowerToys.PdfThumbnailProvider.exe',
|
||||
'PowerToys.PdfThumbnailProviderCpp.dll',
|
||||
'PowerToys.powerpreview.dll',
|
||||
'PowerToys.PreviewHandlerCommon.dll',
|
||||
'PowerToys.QoiPreviewHandler.dll',
|
||||
'PowerToys.QoiPreviewHandler.exe',
|
||||
'PowerToys.QoiPreviewHandlerCpp.dll',
|
||||
'PowerToys.QoiThumbnailProvider.dll',
|
||||
'PowerToys.QoiThumbnailProvider.exe',
|
||||
'PowerToys.QoiThumbnailProviderCpp.dll',
|
||||
'PowerToys.StlThumbnailProvider.dll',
|
||||
'PowerToys.StlThumbnailProvider.exe',
|
||||
'PowerToys.StlThumbnailProviderCpp.dll',
|
||||
'PowerToys.SvgPreviewHandler.dll',
|
||||
'PowerToys.SvgPreviewHandler.exe',
|
||||
'PowerToys.SvgPreviewHandlerCpp.dll',
|
||||
'PowerToys.SvgThumbnailProvider.dll',
|
||||
'PowerToys.SvgThumbnailProvider.exe',
|
||||
'PowerToys.SvgThumbnailProviderCpp.dll',
|
||||
|
||||
# Image Resizer
|
||||
'PowerToys.ImageResizer.exe',
|
||||
'PowerToys.ImageResizer.dll',
|
||||
'PowerToys.ImageResizerExt.dll',
|
||||
'PowerToys.ImageResizerContextMenu.dll',
|
||||
|
||||
# Keyboard Manager
|
||||
'PowerToys.KeyboardManager.dll',
|
||||
'PowerToys.KeyboardManagerEditorLibraryWrapper.dll',
|
||||
|
||||
# PowerToys Run
|
||||
'PowerToys.Launcher.dll',
|
||||
'PowerToys.PowerLauncher.dll',
|
||||
'PowerToys.PowerLauncher.exe',
|
||||
'PowerToys.PowerLauncher.Telemetry.dll',
|
||||
'Wox.Infrastructure.dll',
|
||||
'Wox.Plugin.dll',
|
||||
|
||||
# Mouse utilities
|
||||
'PowerToys.FindMyMouse.dll',
|
||||
'PowerToys.MouseHighlighter.dll',
|
||||
'PowerToys.MouseJump.dll',
|
||||
'PowerToys.MouseJump.Common.dll',
|
||||
'PowerToys.MousePointerCrosshairs.dll',
|
||||
'PowerToys.MouseJumpUI.dll',
|
||||
'PowerToys.MouseJumpUI.exe',
|
||||
'PowerToys.MouseWithoutBorders.dll',
|
||||
'PowerToys.MouseWithoutBorders.exe',
|
||||
'PowerToys.MouseWithoutBordersModuleInterface.dll',
|
||||
'PowerToys.MouseWithoutBordersService.dll',
|
||||
'PowerToys.MouseWithoutBordersService.exe',
|
||||
'PowerToys.MouseWithoutBordersHelper.dll',
|
||||
'PowerToys.MouseWithoutBordersHelper.exe',
|
||||
|
||||
# PowerAccent
|
||||
'PowerAccent.Core.dll',
|
||||
'PowerToys.PowerAccent.dll',
|
||||
'PowerToys.PowerAccent.exe',
|
||||
'PowerToys.PowerAccentModuleInterface.dll',
|
||||
'PowerToys.PowerAccentKeyboardService.dll',
|
||||
|
||||
# Workspaces
|
||||
'PowerToys.WorkspacesSnapshotTool.exe',
|
||||
'PowerToys.WorkspacesLauncher.exe',
|
||||
'PowerToys.WorkspacesWindowArranger.exe',
|
||||
'PowerToys.WorkspacesEditor.exe',
|
||||
'PowerToys.WorkspacesEditor.dll',
|
||||
'PowerToys.WorkspacesLauncherUI.exe',
|
||||
'PowerToys.WorkspacesLauncherUI.dll',
|
||||
'PowerToys.WorkspacesModuleInterface.dll',
|
||||
'PowerToys.WorkspacesCsharpLibrary.dll',
|
||||
|
||||
# Shortcut Guide
|
||||
'PowerToys.ShortcutGuide.exe',
|
||||
'PowerToys.ShortcutGuideModuleInterface.dll',
|
||||
|
||||
# ZoomIt
|
||||
'PowerToys.ZoomIt.exe',
|
||||
'PowerToys.ZoomItModuleInterface.dll',
|
||||
'PowerToys.ZoomItSettingsInterop.dll',
|
||||
|
||||
# Command Palette
|
||||
'PowerToys.CmdPalModuleInterface.dll',
|
||||
'CmdPalKeyboardService.dll'
|
||||
)
|
||||
|
||||
# WinUI3Apps signed files (in WinUI3Apps subdirectory)
|
||||
$winUI3SignedFiles = @(
|
||||
'PowerToys.Settings.dll',
|
||||
'PowerToys.Settings.exe',
|
||||
'PowerToys.AdvancedPaste.exe',
|
||||
'PowerToys.AdvancedPaste.dll',
|
||||
'PowerToys.HostsModuleInterface.dll',
|
||||
'PowerToys.HostsUILib.dll',
|
||||
'PowerToys.Hosts.dll',
|
||||
'PowerToys.Hosts.exe',
|
||||
'PowerToys.FileLocksmithLib.Interop.dll',
|
||||
'PowerToys.FileLocksmithExt.dll',
|
||||
'PowerToys.FileLocksmithUI.exe',
|
||||
'PowerToys.FileLocksmithUI.dll',
|
||||
'PowerToys.FileLocksmithContextMenu.dll',
|
||||
'Peek.Common.dll',
|
||||
'Peek.FilePreviewer.dll',
|
||||
'Powertoys.Peek.UI.dll',
|
||||
'Powertoys.Peek.UI.exe',
|
||||
'Powertoys.Peek.dll',
|
||||
'PowerToys.EnvironmentVariablesModuleInterface.dll',
|
||||
'PowerToys.EnvironmentVariablesUILib.dll',
|
||||
'PowerToys.EnvironmentVariables.dll',
|
||||
'PowerToys.EnvironmentVariables.exe',
|
||||
'PowerToys.MeasureToolModuleInterface.dll',
|
||||
'PowerToys.MeasureToolCore.dll',
|
||||
'PowerToys.MeasureToolUI.dll',
|
||||
'PowerToys.MeasureToolUI.exe',
|
||||
'PowerToys.NewPlus.ShellExtension.dll',
|
||||
'PowerToys.NewPlus.ShellExtension.win10.dll',
|
||||
'PowerToys.PowerRenameExt.dll',
|
||||
'PowerToys.PowerRename.exe',
|
||||
'PowerToys.PowerRenameContextMenu.dll',
|
||||
'PowerToys.RegistryPreviewExt.dll',
|
||||
'PowerToys.RegistryPreviewUILib.dll',
|
||||
'PowerToys.RegistryPreview.dll',
|
||||
'PowerToys.RegistryPreview.exe'
|
||||
)
|
||||
|
||||
# Tools signed files (in Tools subdirectory)
|
||||
$toolsSignedFiles = @(
|
||||
'PowerToys.BugReportTool.exe'
|
||||
)
|
||||
|
||||
# KeyboardManager signed files (in specific subdirectories)
|
||||
$keyboardManagerFiles = @{
|
||||
'KeyboardManagerEditor\PowerToys.KeyboardManagerEditor.exe' = 'KeyboardManagerEditor'
|
||||
'KeyboardManagerEngine\PowerToys.KeyboardManagerEngine.exe' = 'KeyboardManagerEngine'
|
||||
}
|
||||
|
||||
# Run plugins signed files (in RunPlugins subdirectories)
|
||||
$runPluginFiles = @{
|
||||
'RunPlugins\Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.dll' = 'Calculator plugin'
|
||||
'RunPlugins\Folder\Microsoft.Plugin.Folder.dll' = 'Folder plugin'
|
||||
'RunPlugins\Indexer\Microsoft.Plugin.Indexer.dll' = 'Indexer plugin'
|
||||
'RunPlugins\OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.dll' = 'OneNote plugin'
|
||||
'RunPlugins\History\Microsoft.PowerToys.Run.Plugin.History.dll' = 'History plugin'
|
||||
'RunPlugins\PowerToys\Microsoft.PowerToys.Run.Plugin.PowerToys.dll' = 'PowerToys plugin'
|
||||
'RunPlugins\Program\Microsoft.Plugin.Program.dll' = 'Program plugin'
|
||||
'RunPlugins\Registry\Microsoft.PowerToys.Run.Plugin.Registry.dll' = 'Registry plugin'
|
||||
'RunPlugins\WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.dll' = 'Windows Settings plugin'
|
||||
'RunPlugins\Shell\Microsoft.Plugin.Shell.dll' = 'Shell plugin'
|
||||
'RunPlugins\Uri\Microsoft.Plugin.Uri.dll' = 'URI plugin'
|
||||
'RunPlugins\WindowWalker\Microsoft.Plugin.WindowWalker.dll' = 'Window Walker plugin'
|
||||
'RunPlugins\UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.dll' = 'Unit Converter plugin'
|
||||
'RunPlugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.dll' = 'VS Code Workspaces plugin'
|
||||
'RunPlugins\Service\Microsoft.PowerToys.Run.Plugin.Service.dll' = 'Service plugin'
|
||||
'RunPlugins\System\Microsoft.PowerToys.Run.Plugin.System.dll' = 'System plugin'
|
||||
'RunPlugins\TimeDate\Microsoft.PowerToys.Run.Plugin.TimeDate.dll' = 'Time Date plugin'
|
||||
'RunPlugins\ValueGenerator\Community.PowerToys.Run.Plugin.ValueGenerator.dll' = 'Value Generator plugin'
|
||||
'RunPlugins\WebSearch\Community.PowerToys.Run.Plugin.WebSearch.dll' = 'Web Search plugin'
|
||||
'RunPlugins\WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.dll' = 'Windows Terminal plugin'
|
||||
}
|
||||
|
||||
# Check essential core files (must exist)
|
||||
Write-StatusMessage "Checking essential core files..." -Level Info
|
||||
foreach ($file in $essentialCoreFiles) {
|
||||
$filePath = Join-Path $InstallPath $file
|
||||
$exists = Test-Path $filePath
|
||||
Add-CheckResult -Category "Core Files" -CheckName "$file ($Scope)" -Status $(if ($exists) { 'Pass' } else { 'Fail' }) -Message "Essential file: $filePath"
|
||||
}
|
||||
|
||||
# Check critical signed files in root directory
|
||||
Write-StatusMessage "Checking critical signed files in root directory..." -Level Info
|
||||
foreach ($file in $criticalSignedFiles) {
|
||||
$filePath = Join-Path $InstallPath $file
|
||||
$exists = Test-Path $filePath
|
||||
# Most signed files are critical, but some may be optional depending on configuration
|
||||
$status = if ($exists) { 'Pass' } else { 'Warning' }
|
||||
Add-CheckResult -Category "Signed Files" -CheckName "$file ($Scope)" -Status $status -Message "Signed file: $filePath"
|
||||
}
|
||||
|
||||
# Check WinUI3Apps signed files
|
||||
Write-StatusMessage "Checking WinUI3Apps signed files..." -Level Info
|
||||
foreach ($file in $winUI3SignedFiles) {
|
||||
$filePath = Join-Path $InstallPath "WinUI3Apps\$file"
|
||||
$exists = Test-Path $filePath
|
||||
$status = if ($exists) { 'Pass' } else { 'Warning' }
|
||||
Add-CheckResult -Category "Signed Files" -CheckName "WinUI3Apps\$file ($Scope)" -Status $status -Message "WinUI3 signed file: $filePath"
|
||||
}
|
||||
|
||||
# Check Tools signed files
|
||||
Write-StatusMessage "Checking Tools signed files..." -Level Info
|
||||
foreach ($file in $toolsSignedFiles) {
|
||||
$filePath = Join-Path $InstallPath "Tools\$file"
|
||||
$exists = Test-Path $filePath
|
||||
$status = if ($exists) { 'Pass' } else { 'Warning' }
|
||||
Add-CheckResult -Category "Signed Files" -CheckName "Tools\$file ($Scope)" -Status $status -Message "Tools signed file: $filePath"
|
||||
}
|
||||
|
||||
# Check KeyboardManager files
|
||||
Write-StatusMessage "Checking KeyboardManager signed files..." -Level Info
|
||||
foreach ($relativePath in $keyboardManagerFiles.Keys) {
|
||||
$filePath = Join-Path $InstallPath $relativePath
|
||||
$exists = Test-Path $filePath
|
||||
$status = if ($exists) { 'Pass' } else { 'Warning' }
|
||||
$description = $keyboardManagerFiles[$relativePath]
|
||||
Add-CheckResult -Category "Signed Files" -CheckName "$relativePath ($Scope)" -Status $status -Message "KeyboardManager $description signed file: $filePath"
|
||||
}
|
||||
|
||||
# Check Run plugins files
|
||||
Write-StatusMessage "Checking PowerToys Run plugin files..." -Level Info
|
||||
foreach ($relativePath in $runPluginFiles.Keys) {
|
||||
$filePath = Join-Path $InstallPath $relativePath
|
||||
$exists = Test-Path $filePath
|
||||
$status = if ($exists) { 'Pass' } else { 'Warning' }
|
||||
$description = $runPluginFiles[$relativePath]
|
||||
Add-CheckResult -Category "Signed Files" -CheckName "$relativePath ($Scope)" -Status $status -Message "PowerToys Run $description signed file: $filePath"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-ModuleFiles {
|
||||
param(
|
||||
[string]$InstallPath,
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
# PowerToys does not actually install modules in a "modules" subfolder.
|
||||
# Instead, modules are integrated directly into the main installation or specific subfolders.
|
||||
# Check for key module directories that should exist:
|
||||
|
||||
# Check KeyboardManager components (installed as separate folders)
|
||||
$keyboardManagerEditor = Join-Path $InstallPath "KeyboardManagerEditor"
|
||||
$keyboardManagerEngine = Join-Path $InstallPath "KeyboardManagerEngine"
|
||||
|
||||
if (Test-Path $keyboardManagerEditor) {
|
||||
Add-CheckResult -Category "Modules" -CheckName "KeyboardManager Editor ($Scope)" -Status 'Pass' -Message "KeyboardManager Editor folder exists: $keyboardManagerEditor"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Modules" -CheckName "KeyboardManager Editor ($Scope)" -Status 'Warning' -Message "KeyboardManager Editor folder not found: $keyboardManagerEditor"
|
||||
}
|
||||
|
||||
if (Test-Path $keyboardManagerEngine) {
|
||||
Add-CheckResult -Category "Modules" -CheckName "KeyboardManager Engine ($Scope)" -Status 'Pass' -Message "KeyboardManager Engine folder exists: $keyboardManagerEngine"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Modules" -CheckName "KeyboardManager Engine ($Scope)" -Status 'Warning' -Message "KeyboardManager Engine folder not found: $keyboardManagerEngine"
|
||||
}
|
||||
|
||||
# Check RunPlugins folder (contains PowerToys Run modules)
|
||||
$runPluginsPath = Join-Path $InstallPath "RunPlugins"
|
||||
if (Test-Path $runPluginsPath) {
|
||||
Add-CheckResult -Category "Modules" -CheckName "Run Plugins Folder ($Scope)" -Status 'Pass' -Message "Run plugins folder exists: $runPluginsPath"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Modules" -CheckName "Run Plugins Folder ($Scope)" -Status 'Warning' -Message "Run plugins folder not found: $runPluginsPath"
|
||||
}
|
||||
|
||||
# Check Tools folder
|
||||
$toolsPath = Join-Path $InstallPath "Tools"
|
||||
if (Test-Path $toolsPath) {
|
||||
Add-CheckResult -Category "Modules" -CheckName "Tools Folder ($Scope)" -Status 'Pass' -Message "Tools folder exists: $toolsPath"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Modules" -CheckName "Tools Folder ($Scope)" -Status 'Warning' -Message "Tools folder not found: $toolsPath"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-RegistryHandlers {
|
||||
param(
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
$registryRoot = if ($Scope -eq 'PerMachine') { 'HKLM:' } else { 'HKCU:' }
|
||||
# Test URL protocol handler
|
||||
$protocolPath = "$registryRoot\SOFTWARE\Classes\powertoys"
|
||||
if (Test-RegistryKey -Path $protocolPath) {
|
||||
Add-CheckResult -Category "Registry Handlers" -CheckName "PowerToys URL Protocol ($Scope)" -Status 'Pass' -Message "URL protocol registered"
|
||||
|
||||
# Check command handler
|
||||
$commandPath = "$protocolPath\shell\open\command"
|
||||
if (Test-RegistryKey -Path $commandPath) {
|
||||
Add-CheckResult -Category "Registry Handlers" -CheckName "PowerToys URL Command ($Scope)" -Status 'Pass' -Message "URL command handler registered"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Registry Handlers" -CheckName "PowerToys URL Command ($Scope)" -Status 'Fail' -Message "URL command handler not found"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Registry Handlers" -CheckName "PowerToys URL Protocol ($Scope)" -Status 'Fail' -Message "URL protocol not registered"
|
||||
}
|
||||
|
||||
# Test CLSID registration for toast notifications
|
||||
$toastClsidPath = "$registryRoot\SOFTWARE\Classes\CLSID\{DD5CACDA-7C2E-4997-A62A-04A597B58F76}"
|
||||
if (Test-RegistryKey -Path $toastClsidPath) {
|
||||
Add-CheckResult -Category "Registry Handlers" -CheckName "Toast Notification CLSID ($Scope)" -Status 'Pass' -Message "Toast notification CLSID registered"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Registry Handlers" -CheckName "Toast Notification CLSID ($Scope)" -Status 'Warning' -Message "Toast notification CLSID not found"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-DSCModule {
|
||||
param(
|
||||
[string]$Scope
|
||||
)
|
||||
|
||||
if ($Scope -eq 'PerUser') {
|
||||
# For per-user installations, DSC module is installed via custom action to user's Documents
|
||||
$userModulesPath = "$env:USERPROFILE\Documents\PowerShell\Modules\Microsoft.PowerToys.Configure"
|
||||
if (Test-Path $userModulesPath) {
|
||||
Add-CheckResult -Category "DSC Module" -CheckName "DSC Module (PerUser)" -Status 'Pass' -Message "DSC module found in user profile: $userModulesPath"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "DSC Module" -CheckName "DSC Module (PerUser)" -Status 'Fail' -Message "DSC module not found in user profile: $userModulesPath"
|
||||
}
|
||||
}
|
||||
else {
|
||||
# For per-machine installations, DSC module is installed to system WindowsPowerShell modules
|
||||
$systemModulesPath = "${env:ProgramFiles}\WindowsPowerShell\Modules\Microsoft.PowerToys.Configure"
|
||||
if (Test-Path $systemModulesPath) {
|
||||
Add-CheckResult -Category "DSC Module" -CheckName "DSC Module (PerMachine)" -Status 'Pass' -Message "DSC module found in system modules: $systemModulesPath"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "DSC Module" -CheckName "DSC Module (PerMachine)" -Status 'Fail' -Message "DSC module not found in system modules: $systemModulesPath"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Test-CommandPalettePackages {
|
||||
param(
|
||||
[string]$InstallPath
|
||||
)
|
||||
|
||||
$cmdPalPath = Join-Path $InstallPath "WinUI3Apps\CmdPal"
|
||||
if (Test-Path $cmdPalPath) {
|
||||
# Check for MSIX package file (the actual Command Palette installation)
|
||||
$msixFiles = Get-ChildItem $cmdPalPath -Filter "*.msix" -ErrorAction SilentlyContinue
|
||||
if ($msixFiles) {
|
||||
Add-CheckResult -Category "Command Palette" -CheckName "CmdPal MSIX Package" -Status 'Pass' -Message "Found $($msixFiles.Count) Command Palette MSIX package(s)"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Command Palette" -CheckName "CmdPal MSIX Package" -Status 'Warning' -Message "No Command Palette MSIX packages found"
|
||||
}
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Command Palette" -CheckName "CmdPal Module" -Status 'Warning' -Message "Command Palette module not found at: $cmdPalPath"
|
||||
}
|
||||
}
|
||||
|
||||
function Test-ContextMenuPackages {
|
||||
param(
|
||||
[string]$InstallPath
|
||||
)
|
||||
|
||||
# Context menu packages are installed as sparse packages
|
||||
# These MSIX packages should be present in the installation
|
||||
$contextMenuPackages = @{
|
||||
"ImageResizerContextMenuPackage.msix" = @{ Name = "Image Resizer context menu package"; Location = "Root" }
|
||||
"FileLocksmithContextMenuPackage.msix" = @{ Name = "File Locksmith context menu package"; Location = "WinUI3Apps" }
|
||||
"PowerRenameContextMenuPackage.msix" = @{ Name = "PowerRename context menu package"; Location = "WinUI3Apps" }
|
||||
"NewPlusPackage.msix" = @{ Name = "New+ context menu package"; Location = "WinUI3Apps" }
|
||||
}
|
||||
|
||||
# Check for packages based on their expected location
|
||||
foreach ($packageFile in $contextMenuPackages.Keys) {
|
||||
$packageInfo = $contextMenuPackages[$packageFile]
|
||||
|
||||
if ($packageInfo.Location -eq "Root") {
|
||||
$packagePath = Join-Path $InstallPath $packageFile
|
||||
}
|
||||
else {
|
||||
$packagePath = Join-Path $InstallPath "WinUI3Apps\$packageFile"
|
||||
}
|
||||
|
||||
if (Test-Path $packagePath) {
|
||||
Add-CheckResult -Category "Context Menu Packages" -CheckName $packageInfo.Name -Status 'Pass' -Message "Context menu package found: $packagePath"
|
||||
}
|
||||
else {
|
||||
Add-CheckResult -Category "Context Menu Packages" -CheckName $packageInfo.Name -Status 'Fail' -Message "Context menu package not found: $packagePath"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Main execution
|
||||
function Main {
|
||||
Write-StatusMessage "Starting PowerToys Installation Verification" -Level Info
|
||||
Write-StatusMessage "Scope: $InstallScope" -Level Info
|
||||
|
||||
# Check the specified scope - no fallbacks, only what installer should create
|
||||
$installationFound = $false
|
||||
|
||||
if ($InstallScope -eq 'PerMachine') {
|
||||
if (Test-PowerToysInstallation -Scope 'PerMachine') {
|
||||
$installationFound = $true
|
||||
Test-RegistryHandlers -Scope 'PerMachine'
|
||||
Test-DSCModule -Scope 'PerMachine'
|
||||
$installPath = Get-PowerToysInstallPath -Scope 'PerMachine'
|
||||
if ($installPath) {
|
||||
Test-CommandPalettePackages -InstallPath $installPath
|
||||
Test-ContextMenuPackages -InstallPath $installPath
|
||||
}
|
||||
}
|
||||
}
|
||||
else { # PerUser
|
||||
if (Test-PowerToysInstallation -Scope 'PerUser') {
|
||||
$installationFound = $true
|
||||
Test-RegistryHandlers -Scope 'PerUser'
|
||||
Test-DSCModule -Scope 'PerUser'
|
||||
$installPath = Get-PowerToysInstallPath -Scope 'PerUser'
|
||||
if ($installPath) {
|
||||
Test-CommandPalettePackages -InstallPath $installPath
|
||||
Test-ContextMenuPackages -InstallPath $installPath
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($installationFound) {
|
||||
# Common tests (only run if installation found)
|
||||
# Note: Scheduled tasks are not created by installer, they're created at runtime
|
||||
}
|
||||
|
||||
# Calculate overall status
|
||||
if ($script:Results.Summary.FailedChecks -eq 0) {
|
||||
if ($script:Results.Summary.WarningChecks -eq 0) {
|
||||
$script:Results.Summary.OverallStatus = "Healthy"
|
||||
}
|
||||
else {
|
||||
$script:Results.Summary.OverallStatus = "Healthy with Warnings"
|
||||
}
|
||||
}
|
||||
else {
|
||||
$script:Results.Summary.OverallStatus = "Issues Detected"
|
||||
}
|
||||
|
||||
# Display summary
|
||||
Write-Host "`n" -NoNewline
|
||||
Write-StatusMessage "=== VERIFICATION SUMMARY ===" -Level Info
|
||||
Write-StatusMessage "Total Checks: $($script:Results.Summary.TotalChecks)" -Level Info
|
||||
Write-StatusMessage "Passed: $($script:Results.Summary.PassedChecks)" -Level Success
|
||||
Write-StatusMessage "Failed: $($script:Results.Summary.FailedChecks)" -Level Error
|
||||
Write-StatusMessage "Warnings: $($script:Results.Summary.WarningChecks)" -Level Warning
|
||||
Write-StatusMessage "Overall Status: $($script:Results.Summary.OverallStatus)" -Level $(
|
||||
switch ($script:Results.Summary.OverallStatus) {
|
||||
'Healthy' { 'Success' }
|
||||
'Healthy with Warnings' { 'Warning' }
|
||||
default { 'Error' }
|
||||
}
|
||||
)
|
||||
|
||||
Write-StatusMessage "PowerToys Installation Verification Complete" -Level Info
|
||||
}
|
||||
|
||||
# Run the main function
|
||||
Main
|
||||
@@ -7,7 +7,7 @@ This script automates the end-to-end build and packaging process for PowerToys,
|
||||
- Restoring and building all necessary solutions (CmdPal, BugReportTool, etc.)
|
||||
- Cleaning up old output
|
||||
- Signing generated .msix packages
|
||||
- Building the WiX-based MSI and bootstrapper installers
|
||||
- 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
|
||||
@@ -21,9 +21,12 @@ Specifies the build configuration (e.g., 'Debug', 'Release'). Default is 'Releas
|
||||
.PARAMETER PerUser
|
||||
Specifies whether to build a per-user installer (true) or machine-wide installer (false). Default is true (per-user).
|
||||
|
||||
.PARAMETER InstallerSuffix
|
||||
Specifies the suffix for the installer naming (e.g., 'wix5', 'vnext'). Default is 'wix5'.
|
||||
|
||||
.EXAMPLE
|
||||
.\build-installer.ps1
|
||||
Runs the installer build pipeline for ARM64 Release (default).
|
||||
Runs the installer build pipeline for x64 Release with default suffix (wix5).
|
||||
|
||||
.EXAMPLE
|
||||
.\build-installer.ps1 -Platform x64 -Configuration Release
|
||||
@@ -33,12 +36,16 @@ Runs the pipeline for x64 Release.
|
||||
.\build-installer.ps1 -Platform x64 -Configuration Release -PerUser false
|
||||
Runs the pipeline for x64 Release with machine-wide installer.
|
||||
|
||||
.EXAMPLE
|
||||
.\build-installer.ps1 -Platform x64 -Configuration Release -InstallerSuffix vnext
|
||||
Runs the pipeline for x64 Release with 'vnext' suffix.
|
||||
|
||||
.NOTES
|
||||
- Make sure to run this script from a Developer PowerShell (e.g., VS2022 Developer PowerShell).
|
||||
- Generated MSIX files will be signed using cert-sign-package.ps1.
|
||||
- This script will clean previous outputs under the build directories and installer directory (except *.exe files).
|
||||
- First time run need admin permission to trust the certificate.
|
||||
- The built installer will be placed under: installer/PowerToysSetup/[Platform]/[Configuration]/User[Machine]Setup
|
||||
- The built installer will be placed under: installer/PowerToysSetupVNext/[Platform]/[Configuration]/User[Machine]Setup
|
||||
relative to the solution root directory.
|
||||
- To run the full installation in other machines, call "./cert-management.ps1" to export the cert used to sign the packages.
|
||||
And trust the cert in the target machine.
|
||||
@@ -47,7 +54,8 @@ Runs the pipeline for x64 Release with machine-wide installer.
|
||||
param (
|
||||
[string]$Platform = 'x64',
|
||||
[string]$Configuration = 'Release',
|
||||
[string]$PerUser = 'true'
|
||||
[string]$PerUser = 'true',
|
||||
[string]$InstallerSuffix = 'wix5'
|
||||
)
|
||||
|
||||
# Find the PowerToys repository root automatically
|
||||
@@ -114,8 +122,7 @@ function RestoreThenBuild {
|
||||
RunMSBuild $Solution '/m'
|
||||
}
|
||||
|
||||
Write-Host ("Make sure wix is installed and available")
|
||||
& (Join-Path $PSScriptRoot "ensure-wix.ps1")
|
||||
# WiX v5 projects use WixToolset.Sdk via NuGet/MSBuild; a separate WiX 3 installation is not required here.
|
||||
|
||||
Write-Host ("[PIPELINE] Start | Platform={0} Configuration={1} PerUser={2}" -f $Platform, $Configuration, $PerUser)
|
||||
Write-Host ''
|
||||
@@ -154,8 +161,8 @@ try {
|
||||
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' '/t:restore /p:RestorePackagesConfig=true'
|
||||
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "/m /t:PowerToysInstaller /p:PerUser=$PerUser"
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "/m /t:PowerToysInstallerVNext /p:PerUser=$PerUser /p:InstallerSuffix=$InstallerSuffix"
|
||||
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "/m /t:PowerToysBootstrapper /p:PerUser=$PerUser"
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "/m /t:PowerToysBootstrapperVNext /p:PerUser=$PerUser /p:InstallerSuffix=$InstallerSuffix"
|
||||
|
||||
Write-Host '[PIPELINE] Completed'
|
||||
|
||||
Reference in New Issue
Block a user