Merge remote-tracking branch 'origin/main' into dev/snickler/net10-upgrade

This commit is contained in:
Jeremy Sinclair
2025-11-03 19:51:15 -05:00
13 changed files with 424 additions and 284 deletions

View File

@@ -97,6 +97,7 @@ atl
ATX
ATRIOX
aumid
authenticode
Authenticode
AUTOBUDDY
AUTOCHECKBOX
@@ -142,6 +143,7 @@ bmi
BNumber
BODGY
BOklab
Bootstrappers
BOOTSTRAPPERINSTALLFOLDER
BOTTOMALIGN
boxmodel
@@ -1030,6 +1032,7 @@ msiexec
MSIFASTINSTALL
MSIHANDLE
MSIRESTARTMANAGERCONTROL
MSIs
msixbundle
MSIXCA
MSLLHOOKSTRUCT

View File

@@ -1,53 +0,0 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
"PowerToysSetupCustomActionsVNext.dll",
"SilentFilesInUseBAFunction.dll",
"PowerToys*Setup-*.exe",
"PowerToys*Setup-*.msi"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}

View File

@@ -512,14 +512,6 @@ jobs:
versionNumber: ${{ parameters.versionNumber }}
additionalBuildOptions: ${{ parameters.additionalBuildOptions }}
- template: steps-build-installer-vnext.yml
parameters:
codeSign: ${{ parameters.codeSign }}
signingIdentity: ${{ parameters.signingIdentity }}
versionNumber: ${{ parameters.versionNumber }}
additionalBuildOptions: ${{ parameters.additionalBuildOptions }}
buildUserInstaller: true # NOTE: This is the distinction between the above and below rules
# This saves ~1GiB per architecture. We won't need these later.
# Removes:
# - All .pdb files from any static libs .libs (which were only used during linking)

View File

@@ -2,9 +2,6 @@ parameters:
- name: versionNumber
type: string
default: "0.0.1"
- name: buildUserInstaller
type: boolean
default: false
- name: codeSign
type: boolean
default: false
@@ -25,43 +22,26 @@ steps:
arguments: 'install --global wix --version 5.0.2'
- pwsh: |-
& git clean -xfd -e *exe -- .\installer\
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Clean installer to reduce cross-contamination
- pwsh: |-
# Determine whether this is a per-user build
$IsPerUser = $${{ parameters.buildUserInstaller }}
# Build slug used to locate the artifacts
$InstallerBuildSlug = if ($IsPerUser) { 'UserSetup' } else { 'MachineSetup' }
# VNext bundle folder; base name intentionally omits the VNext suffix
$InstallerFolder = 'PowerToysSetupVNext'
if ($IsPerUser) {
$InstallerBasename = "PowerToysUserSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
}
else {
$InstallerBasename = "PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
}
# Export variables for downstream steps
Write-Host "##vso[task.setvariable variable=InstallerBuildSlug]$InstallerBuildSlug"
Write-Host "##vso[task.setvariable variable=InstallerRelativePath]$(BuildPlatform)\$(BuildConfiguration)\$InstallerBuildSlug"
Write-Host "##vso[task.setvariable variable=InstallerBasename]$InstallerBasename"
Write-Host "##vso[task.setvariable variable=InstallerFolder]$InstallerFolder"
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Prepare Installer variables
Write-Host "##vso[task.setvariable variable=InstallerMachineRoot]installer\PowerToysSetupVNext\$(BuildPlatform)\$(BuildConfiguration)\MachineSetup"
Write-Host "##vso[task.setvariable variable=InstallerUserRoot]installer\PowerToysSetupVNext\$(BuildPlatform)\$(BuildConfiguration)\UserSetup"
Write-Host "##vso[task.setvariable variable=InstallerMachineBasename]PowerToysSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
Write-Host "##vso[task.setvariable variable=InstallerUserBasename]PowerToysUserSetup-${{ parameters.versionNumber }}-$(BuildPlatform)"
displayName: Prepare Installer variables
# This dll needs to be built and signed before building the MSI.
# The Custom Actions project contains a pre-build event that prepares the .wxs files
# by filling them out with all our components. We pass RunBuildEvents=true to force
# that logic to run.
- task: VSBuild@1
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build PowerToysSetupCustomActionsVNext
displayName: Build Shared Support DLLs
inputs:
solution: "**/installer/PowerToysSetup.sln"
vsVersion: 17.0
msbuildArgs: >-
/t:PowerToysSetupCustomActionsVNext
/p:RunBuildEvents=true;PerUser=${{parameters.buildUserInstaller}};RestorePackagesConfig=true;CIBuild=true
/t:PowerToysSetupCustomActionsVNext;SilentFilesInUseBAFunction
/p:RunBuildEvents=true;RestorePackagesConfig=true;CIBuild=true
-restore -graph
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-actions.binlog
/bl:$(LogOutputDirectory)\installer-actions.binlog
${{ parameters.additionalBuildOptions }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
@@ -70,28 +50,53 @@ steps:
maximumCpuCount: true
- ${{ if eq(parameters.codeSign, true) }}:
- template: steps-esrp-signing.yml
- template: steps-esrp-sign-files-authenticode.yml
parameters:
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign PowerToysSetupCustomActionsVNext
displayName: Sign Shared Support DLLs
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: 'installer/PowerToysSetupCustomActionsVNext/$(InstallerRelativePath)'
signType: batchSigning
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
folder: 'installer'
pattern: |-
**/PowerToysSetupCustomActionsVNext.dll
**/SilentFilesInUseBAFunction.dll
## INSTALLER START
#### MSI BUILDING AND SIGNING
#
# The MSI build contains code that reverts the .wxs files to their in-tree versions.
# This is only supposed to happen during local builds. Since this build system is
# supposed to run side by side--machine and then user--we do NOT want to destroy
# the .wxs files. Therefore, we pass RunBuildEvents=false to suppress all of that
# logic.
#
# We pass BuildProjectReferences=false so that it does not recompile the DLLs we just built.
# We only pass -restore on the first one because the second run should already have all
# of the dependencies.
- task: VSBuild@1
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build VNext MSI
displayName: 💻 Build VNext MSI
inputs:
solution: "**/installer/PowerToysSetup.sln"
vsVersion: 17.0
msbuildArgs: >-
-restore
/t:PowerToysInstallerVNext
/p:RunBuildEvents=false;PerUser=${{parameters.buildUserInstaller}};BuildProjectReferences=false;CIBuild=true
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-msi.binlog
/p:RunBuildEvents=false;PerUser=false;BuildProjectReferences=false;CIBuild=true
/bl:$(LogOutputDirectory)\installer-machine-msi.binlog
${{ parameters.additionalBuildOptions }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
clean: false # don't undo our hard work above by deleting the CustomActions dll
msbuildArchitecture: x64
maximumCpuCount: true
- task: VSBuild@1
displayName: 👤 Build VNext MSI
inputs:
solution: "**/installer/PowerToysSetup.sln"
vsVersion: 17.0
msbuildArgs: >-
/t:PowerToysInstallerVNext
/p:RunBuildEvents=false;PerUser=true;BuildProjectReferences=false;CIBuild=true
/bl:$(LogOutputDirectory)\installer-user-msi.binlog
${{ parameters.additionalBuildOptions }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
@@ -100,77 +105,66 @@ steps:
maximumCpuCount: true
- script: |-
wix msi decompile installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).msi -x $(build.sourcesdirectory)\extractedMsi
dir $(build.sourcesdirectory)\extractedMsi
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} WiX5: Extract and verify MSI"
wix msi decompile $(InstallerMachineRoot)\$(InstallerMachineBasename).msi -x $(build.sourcesdirectory)\extractedMachineMsi
wix msi decompile $(InstallerUserRoot)\$(InstallerUserBasename).msi -x $(build.sourcesdirectory)\extractedUserMsi
dir $(build.sourcesdirectory)\extractedMachineMsi
dir $(build.sourcesdirectory)\extractedUserMsi
displayName: "WiX5: Extract and verify MSIs"
# Check if deps.json files don't reference different dll versions.
- pwsh: |-
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Audit deps.json in MSI extracted files
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedMachineMsi\File'
& '.pipelines/verifyDepsJsonLibraryVersions.ps1' -targetDir '$(build.sourcesdirectory)\extractedUserMsi\File'
displayName: Audit deps.json in MSI extracted files
- ${{ if eq(parameters.codeSign, true) }}:
- pwsh: |-
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMsi\File'
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMsi\Binary'
git clean -xfd ./extractedMsi
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Verify all binaries are signed and versioned
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMachineMsi\File'
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedMachineMsi\Binary'
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedUserMsi\File'
& .pipelines/versionAndSignCheck.ps1 -targetDir '$(build.sourcesdirectory)\extractedUserMsi\Binary'
git clean -xfd ./extractedMachineMsi ./extractedUserMsi
displayName: Verify all binaries are signed and versioned
- template: steps-esrp-signing.yml
- template: steps-esrp-sign-files-authenticode.yml
parameters:
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign VNext MSI
displayName: Sign VNext MSIs
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: 'installer/$(InstallerFolder)/$(InstallerRelativePath)'
signType: batchSigning
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
folder: 'installer'
pattern: '**/PowerToys*Setup-*.msi'
#### END MSI
#### BUILDING AND SIGNING SilentFilesInUseBAFunction DLL
- task: VSBuild@1
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build SilentFilesInUseBAFunction
inputs:
solution: "**/installer/PowerToysSetup.sln"
vsVersion: 17.0
msbuildArgs: >-
/t:SilentFilesInUseBAFunction
/p:RunBuildEvents=true;PerUser=${{parameters.buildUserInstaller}};RestorePackagesConfig=true;CIBuild=true
-restore -graph
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-SilentFilesInUseBAFunction.binlog
${{ parameters.additionalBuildOptions }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
clean: false # don't undo our hard work above by deleting the msi
msbuildArchitecture: x64
maximumCpuCount: true
- ${{ if eq(parameters.codeSign, true) }}:
- template: steps-esrp-signing.yml
parameters:
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign SilentFilesInUseBAFunction
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: 'installer/$(BuildPlatform)/$(BuildConfiguration)'
signType: batchSigning
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
#### END BUILDING AND SIGNING SilentFilesInUseBAFunction DLL
#### BOOTSTRAP BUILDING AND SIGNING
# We pass BuildProjectReferences=false so that it does not recompile the DLLs we just built.
# We only pass -restore on the first one because the second run should already have all
# of the dependencies.
- task: VSBuild@1
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Build VNext Bootstrapper
displayName: 💻 Build VNext Bootstrapper
inputs:
solution: "**/installer/PowerToysSetup.sln"
vsVersion: 17.0
msbuildArgs: >-
-restore
/t:PowerToysBootstrapperVNext
/p:PerUser=${{parameters.buildUserInstaller}};CIBuild=true
/bl:$(LogOutputDirectory)\installer-$(InstallerBuildSlug)-bootstrapper.binlog
-restore -graph
/p:PerUser=false;BuildProjectReferences=false;CIBuild=true
/bl:$(LogOutputDirectory)\installer-machine-bootstrapper.binlog
${{ parameters.additionalBuildOptions }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
clean: false # don't undo our hard work above by deleting the MSI nor SilentFilesInUseBAFunction
msbuildArchitecture: x64
maximumCpuCount: true
- task: VSBuild@1
displayName: 👤 Build VNext Bootstrapper
inputs:
solution: "**/installer/PowerToysSetup.sln"
vsVersion: 17.0
msbuildArgs: >-
/t:PowerToysBootstrapperVNext
/p:PerUser=true;BuildProjectReferences=false;CIBuild=true
/bl:$(LogOutputDirectory)\installer-user-bootstrapper.binlog
${{ parameters.additionalBuildOptions }}
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
@@ -181,54 +175,41 @@ steps:
# The entirety of bundle unpacking/re-packing is unnecessary if we are not code signing it.
- ${{ if eq(parameters.codeSign, true) }}:
- script: |-
wix burn detach installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).exe -engine installer\engine.exe
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} WiX5: Extract Engine from Bundle"
wix burn detach $(InstallerMachineRoot)\$(InstallerMachineBasename).exe -engine installer\machine-engine.exe
wix burn detach $(InstallerUserRoot)\$(InstallerUserBasename).exe -engine installer\user-engine.exe
displayName: "WiX5: Extract Engines from Bundles"
- template: steps-esrp-signing.yml
- template: steps-esrp-sign-files-authenticode.yml
parameters:
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign WiX Engine
displayName: Sign WiX Engines
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: "installer"
Pattern: engine.exe
signConfigType: inlineSignParams
inlineOperation: |
[
{
"KeyCode": "CP-230012",
"OperationCode": "SigntoolSign",
"Parameters": {
"OpusName": "Microsoft",
"OpusInfo": "http://www.microsoft.com",
"FileDigest": "/fd \"SHA256\"",
"PageHash": "/NPH",
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationCode": "SigntoolVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
folder: "installer"
pattern: '*-engine.exe'
- script: |-
wix burn reattach installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).exe -engine installer\engine.exe -o installer\$(InstallerFolder)\$(InstallerRelativePath)\$(InstallerBasename).exe
displayName: "${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} WiX5: Reattach Engine to Bundle"
wix burn reattach $(InstallerMachineRoot)\$(InstallerMachineBasename).exe -engine installer\machine-engine.exe -o $(InstallerMachineRoot)\$(InstallerMachineBasename).exe
wix burn reattach $(InstallerUserRoot)\$(InstallerUserBasename).exe -engine installer\user-engine.exe -o $(InstallerUserRoot)\$(InstallerUserBasename).exe
displayName: "WiX5: Reattach Engines to Bundles"
- template: steps-esrp-signing.yml
- pwsh: |-
& wix burn extract -oba installer\ba\m "$(InstallerMachineRoot)\$(InstallerMachineBasename).exe"
& wix burn extract -oba installer\ba\u "$(InstallerUserRoot)\$(InstallerUserBasename).exe"
Get-ChildItem installer\ba -Recurse -Include *.exe,*.dll | Get-AuthenticodeSignature | ForEach-Object {
If ($_.Status -Ne "Valid") {
Write-Error $_.StatusMessage
} Else {
Write-Host $_.StatusMessage
}
}
& git clean -fdx installer\ba
displayName: "WiX5: Verify Bootstrapper content is signed"
- template: steps-esrp-sign-files-authenticode.yml
parameters:
displayName: ${{replace(replace(parameters.buildUserInstaller,'True','👤'),'False','💻')}} Sign Final Bootstrapper
displayName: Sign Final Bootstrappers
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: 'installer/$(InstallerFolder)/$(InstallerRelativePath)'
signType: batchSigning
batchSignPolicyFile: '$(build.sourcesdirectory)\.pipelines\ESRPSigning_installer.json'
ciPolicyFile: '$(build.sourcesdirectory)\.pipelines\CIPolicy.xml'
folder: 'installer'
pattern: '**/PowerToys*Setup-*.exe'
#### END BOOTSTRAP
## END INSTALLER

View File

@@ -0,0 +1,45 @@
parameters:
- name: displayName
type: string
default: Sign Specific Files
- name: folder
type: string
- name: pattern
type: string
- name: signingIdentity
type: object
default: {}
steps:
- template: steps-esrp-signing.yml
parameters:
displayName: ${{ parameters.displayName }}
signingIdentity: ${{ parameters.signingIdentity }}
inputs:
FolderPath: ${{ parameters.folder }}
Pattern: ${{ parameters.pattern }}
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: |-
[
{
"KeyCode": "CP-230012",
"OperationCode": "SigntoolSign",
"Parameters": {
"OpusName": "Microsoft",
"OpusInfo": "http://www.microsoft.com",
"FileDigest": "/fd \"SHA256\"",
"PageHash": "/NPH",
"TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationCode": "SigntoolVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]

View File

@@ -34,12 +34,8 @@
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir Condition=" '$(PerUser)' != 'true' ">$(Platform)\$(Configuration)\MachineSetup\</OutDir>
<OutDir Condition=" '$(PerUser)' == 'true' ">$(Platform)\$(Configuration)\UserSetup\</OutDir>
<IntDir Condition=" '$(PerUser)' != 'true' ">$(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\MachineSetup\obj\</IntDir>
<IntDir Condition=" '$(PerUser)' == 'true' ">$(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\UserSetup\obj\</IntDir>
<NormalizedPerUserValue>false</NormalizedPerUserValue>
<NormalizedPerUserValue Condition=" '$(PerUser)' == 'true' ">true</NormalizedPerUserValue>
<OutDir>$(Platform)\$(Configuration)\SetupShared\</OutDir>
<IntDir>$(SolutionDir)$(ProjectName)\$(Platform)\$(Configuration)\SetupShared\obj\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
<LinkIncremental>true</LinkIncremental>
@@ -79,8 +75,7 @@
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\WinAppSDK.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\WinAppSDK.wxs.bk""""
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\WinUI3Applications.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\WinUI3Applications.wxs.bk""""
call cmd /C "copy ""$(ProjectDir)..\PowerToysSetupVNext\Workspaces.wxs"" ""$(ProjectDir)..\PowerToysSetupVNext\Workspaces.wxs.bk""""
if not "$(NormalizedPerUserValue)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetupVNext\generateAllFileComponents.ps1 -platform $(Platform)
if "$(NormalizedPerUserValue)" == "true" call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetupVNext\generateAllFileComponents.ps1 -platform $(Platform) -installscopeperuser $(NormalizedPerUserValue)
call powershell.exe -NonInteractive -executionpolicy Unrestricted -File ..\PowerToysSetupVNext\generateAllFileComponents.ps1 -platform $(Platform)
</Command>
<Message>Backing up original files and populating .NET and WPF Runtime dependencies for WiX3 based installer</Message>
</PreBuildEvent>
@@ -178,4 +173,4 @@
<Error Condition="!Exists('..\packages\WixToolset.DUtil.5.0.2\build\WixToolset.DUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WixToolset.DUtil.5.0.2\build\WixToolset.DUtil.props'))" />
<Error Condition="!Exists('..\packages\WixToolset.WcaUtil.5.0.2\build\WixToolset.WcaUtil.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\WixToolset.WcaUtil.5.0.2\build\WixToolset.WcaUtil.props'))" />
</Target>
</Project>
</Project>

View File

@@ -60,6 +60,12 @@ call powershell.exe -NonInteractive -executionpolicy Unrestricted -File $(MSBuil
call move /Y ..\..\..\Workspaces.wxs.bk ..\..\..\Workspaces.wxs
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup Condition="'$(RunBuildEvents)'=='false'">
<PostBuildEvent></PostBuildEvent>
<RunPostBuildEvent></RunPostBuildEvent>
<PreBuildEventUseInBuild>false</PreBuildEventUseInBuild>
<PostBuildEventUseInBuild>false</PostBuildEventUseInBuild>
</PropertyGroup>
<PropertyGroup Label="UserMacros" Condition=" '$(PerUser)' == 'true' ">
<DefineConstants>$(DefineConstants);PerUser=true</DefineConstants>
</PropertyGroup>

View File

@@ -1,9 +1,7 @@
[CmdletBinding()]
Param(
[Parameter(Mandatory = $True, Position = 1)]
[string]$platform,
[Parameter(Mandatory = $False, Position = 2)]
[string]$installscopeperuser = "false"
[string]$platform
)
Function Generate-FileList() {
@@ -77,9 +75,7 @@ Function Generate-FileComponents() {
[Parameter(Mandatory = $True, Position = 1)]
[string]$fileListName,
[Parameter(Mandatory = $True, Position = 2)]
[string]$wxsFilePath,
[Parameter(Mandatory = $True, Position = 3)]
[string]$regroot
[string]$wxsFilePath
)
$wxsFile = Get-Content $wxsFilePath;
@@ -100,7 +96,7 @@ Function Generate-FileComponents() {
$componentDefs +=
@"
<Component Id="$($componentId)" Guid="$((New-Guid).ToString().ToUpper())">
<RegistryKey Root="$($regroot)" Key="Software\Classes\powertoys\components">
<RegistryKey Root="`$(var.RegistryScope)" Key="Software\Classes\powertoys\components">
<RegistryValue Type="string" Name="$($componentId)" Value="" KeyPath="yes"/>
</RegistryKey>`r`n
"@
@@ -134,194 +130,188 @@ if ($platform -ceq "arm64") {
$platform = "ARM64"
}
if ($installscopeperuser -eq "true") {
$registryroot = "HKCU"
} else {
$registryroot = "HKLM"
}
#BaseApplications
Generate-FileList -fileDepsJson "" -fileListName BaseApplicationsFiles -wxsFilePath $PSScriptRoot\BaseApplications.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release"
Generate-FileComponents -fileListName "BaseApplicationsFiles" -wxsFilePath $PSScriptRoot\BaseApplications.wxs -regroot $registryroot
Generate-FileComponents -fileListName "BaseApplicationsFiles" -wxsFilePath $PSScriptRoot\BaseApplications.wxs
#WinUI3Applications
Generate-FileList -fileDepsJson "" -fileListName WinUI3ApplicationsFiles -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps"
Generate-FileComponents -fileListName "WinUI3ApplicationsFiles" -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WinUI3ApplicationsFiles" -wxsFilePath $PSScriptRoot\WinUI3Applications.wxs
#AdvancedPaste
Generate-FileList -fileDepsJson "" -fileListName AdvancedPasteAssetsFiles -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\AdvancedPaste"
Generate-FileComponents -fileListName "AdvancedPasteAssetsFiles" -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs -regroot $registryroot
Generate-FileComponents -fileListName "AdvancedPasteAssetsFiles" -wxsFilePath $PSScriptRoot\AdvancedPaste.wxs
#AwakeFiles
Generate-FileList -fileDepsJson "" -fileListName AwakeImagesFiles -wxsFilePath $PSScriptRoot\Awake.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Awake"
Generate-FileComponents -fileListName "AwakeImagesFiles" -wxsFilePath $PSScriptRoot\Awake.wxs -regroot $registryroot
Generate-FileComponents -fileListName "AwakeImagesFiles" -wxsFilePath $PSScriptRoot\Awake.wxs
#ColorPicker
Generate-FileList -fileDepsJson "" -fileListName ColorPickerAssetsFiles -wxsFilePath $PSScriptRoot\ColorPicker.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ColorPicker"
Generate-FileComponents -fileListName "ColorPickerAssetsFiles" -wxsFilePath $PSScriptRoot\ColorPicker.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ColorPickerAssetsFiles" -wxsFilePath $PSScriptRoot\ColorPicker.wxs
#Environment Variables
Generate-FileList -fileDepsJson "" -fileListName EnvironmentVariablesAssetsFiles -wxsFilePath $PSScriptRoot\EnvironmentVariables.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\EnvironmentVariables"
Generate-FileComponents -fileListName "EnvironmentVariablesAssetsFiles" -wxsFilePath $PSScriptRoot\EnvironmentVariables.wxs -regroot $registryroot
Generate-FileComponents -fileListName "EnvironmentVariablesAssetsFiles" -wxsFilePath $PSScriptRoot\EnvironmentVariables.wxs
#FileExplorerAdd-ons
Generate-FileList -fileDepsJson "" -fileListName MonacoPreviewHandlerMonacoAssetsFiles -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Monaco"
Generate-FileList -fileDepsJson "" -fileListName MonacoPreviewHandlerCustomLanguagesFiles -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Monaco\customLanguages"
Generate-FileComponents -fileListName "MonacoPreviewHandlerMonacoAssetsFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -regroot $registryroot
Generate-FileComponents -fileListName "MonacoPreviewHandlerCustomLanguagesFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs -regroot $registryroot
Generate-FileComponents -fileListName "MonacoPreviewHandlerMonacoAssetsFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs
Generate-FileComponents -fileListName "MonacoPreviewHandlerCustomLanguagesFiles" -wxsFilePath $PSScriptRoot\FileExplorerPreview.wxs
#FileLocksmith
Generate-FileList -fileDepsJson "" -fileListName FileLocksmithAssetsFiles -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\FileLocksmith"
Generate-FileComponents -fileListName "FileLocksmithAssetsFiles" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs -regroot $registryroot
Generate-FileComponents -fileListName "FileLocksmithAssetsFiles" -wxsFilePath $PSScriptRoot\FileLocksmith.wxs
#Hosts
Generate-FileList -fileDepsJson "" -fileListName HostsAssetsFiles -wxsFilePath $PSScriptRoot\Hosts.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Hosts"
Generate-FileComponents -fileListName "HostsAssetsFiles" -wxsFilePath $PSScriptRoot\Hosts.wxs -regroot $registryroot
Generate-FileComponents -fileListName "HostsAssetsFiles" -wxsFilePath $PSScriptRoot\Hosts.wxs
#ImageResizer
Generate-FileList -fileDepsJson "" -fileListName ImageResizerAssetsFiles -wxsFilePath $PSScriptRoot\ImageResizer.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\ImageResizer"
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ImageResizerAssetsFiles" -wxsFilePath $PSScriptRoot\ImageResizer.wxs
# Light Switch Service
Generate-FileList -fileDepsJson "" -fileListName LightSwitchFiles -wxsFilePath $PSScriptRoot\LightSwitch.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\LightSwitchService"
Generate-FileComponents -fileListName "LightSwitchFiles" -wxsFilePath $PSScriptRoot\LightSwitch.wxs -regroot $registryroot
Generate-FileComponents -fileListName "LightSwitchFiles" -wxsFilePath $PSScriptRoot\LightSwitch.wxs
#New+
Generate-FileList -fileDepsJson "" -fileListName NewPlusAssetsFiles -wxsFilePath $PSScriptRoot\NewPlus.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\NewPlus"
Generate-FileComponents -fileListName "NewPlusAssetsFiles" -wxsFilePath $PSScriptRoot\NewPlus.wxs -regroot $registryroot
Generate-FileComponents -fileListName "NewPlusAssetsFiles" -wxsFilePath $PSScriptRoot\NewPlus.wxs
#Peek
Generate-FileList -fileDepsJson "" -fileListName PeekAssetsFiles -wxsFilePath $PSScriptRoot\Peek.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Peek\"
Generate-FileComponents -fileListName "PeekAssetsFiles" -wxsFilePath $PSScriptRoot\Peek.wxs -regroot $registryroot
Generate-FileComponents -fileListName "PeekAssetsFiles" -wxsFilePath $PSScriptRoot\Peek.wxs
#PowerRename
Generate-FileList -fileDepsJson "" -fileListName PowerRenameAssetsFiles -wxsFilePath $PSScriptRoot\PowerRename.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\PowerRename\"
Generate-FileComponents -fileListName "PowerRenameAssetsFiles" -wxsFilePath $PSScriptRoot\PowerRename.wxs -regroot $registryroot
Generate-FileComponents -fileListName "PowerRenameAssetsFiles" -wxsFilePath $PSScriptRoot\PowerRename.wxs
#RegistryPreview
Generate-FileList -fileDepsJson "" -fileListName RegistryPreviewAssetsFiles -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\RegistryPreview\"
Generate-FileComponents -fileListName "RegistryPreviewAssetsFiles" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs -regroot $registryroot
Generate-FileComponents -fileListName "RegistryPreviewAssetsFiles" -wxsFilePath $PSScriptRoot\RegistryPreview.wxs
#Run
Generate-FileList -fileDepsJson "" -fileListName launcherImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\PowerLauncher"
Generate-FileComponents -fileListName "launcherImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "launcherImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
## Plugins
###Calculator
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Calculator\Microsoft.PowerToys.Run.Plugin.Calculator.deps.json" -fileListName calcComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName calcImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Calculator\Images"
Generate-FileComponents -fileListName "calcComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "calcImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "calcComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "calcImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Folder
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Folder\Microsoft.Plugin.Folder.deps.json" -fileListName FolderComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName FolderImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Folder\Images"
Generate-FileComponents -fileListName "FolderComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "FolderImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "FolderComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "FolderImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Program
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Program\Microsoft.Plugin.Program.deps.json" -fileListName ProgramComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName ProgramImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Program\Images"
Generate-FileComponents -fileListName "ProgramComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ProgramImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ProgramComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "ProgramImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Shell
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Shell\Microsoft.Plugin.Shell.deps.json" -fileListName ShellComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName ShellImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Shell\Images"
Generate-FileComponents -fileListName "ShellComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ShellImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ShellComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "ShellImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Indexer
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Indexer\Microsoft.Plugin.Indexer.deps.json" -fileListName IndexerComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName IndexerImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Indexer\Images"
Generate-FileComponents -fileListName "IndexerComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "IndexerImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "IndexerComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "IndexerImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###UnitConverter
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\UnitConverter\Community.PowerToys.Run.Plugin.UnitConverter.deps.json" -fileListName UnitConvCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName UnitConvImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\UnitConverter\Images"
Generate-FileComponents -fileListName "UnitConvCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "UnitConvImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "UnitConvCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "UnitConvImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###WebSearch
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WebSearch\Community.PowerToys.Run.Plugin.WebSearch.deps.json" -fileListName WebSrchCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName WebSrchImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WebSearch\Images"
Generate-FileComponents -fileListName "WebSrchCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WebSrchImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WebSrchCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "WebSrchImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###History
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\History\Microsoft.PowerToys.Run.Plugin.History.deps.json" -fileListName HistoryPluginComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName HistoryPluginImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\History\Images"
Generate-FileComponents -fileListName "HistoryPluginComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "HistoryPluginImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "HistoryPluginComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "HistoryPluginImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Uri
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Uri\Microsoft.Plugin.Uri.deps.json" -fileListName UriComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName UriImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Uri\Images"
Generate-FileComponents -fileListName "UriComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "UriImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "UriComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "UriImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###VSCodeWorkspaces
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\VSCodeWorkspaces\Community.PowerToys.Run.Plugin.VSCodeWorkspaces.deps.json" -fileListName VSCWrkCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName VSCWrkImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\VSCodeWorkspaces\Images"
Generate-FileComponents -fileListName "VSCWrkCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "VSCWrkImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "VSCWrkCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "VSCWrkImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###WindowWalker
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowWalker\Microsoft.Plugin.WindowWalker.deps.json" -fileListName WindowWlkrCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName WindowWlkrImagesCompFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowWalker\Images"
Generate-FileComponents -fileListName "WindowWlkrCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WindowWlkrImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WindowWlkrCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "WindowWlkrImagesCompFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###OneNote
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\OneNote\Microsoft.PowerToys.Run.Plugin.OneNote.deps.json" -fileListName OneNoteComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName OneNoteImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\OneNote\Images"
Generate-FileComponents -fileListName "OneNoteComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "OneNoteImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "OneNoteComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "OneNoteImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Registry
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Registry\Microsoft.PowerToys.Run.Plugin.Registry.deps.json" -fileListName RegistryComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName RegistryImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Registry\Images"
Generate-FileComponents -fileListName "RegistryComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "RegistryImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "RegistryComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "RegistryImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###Service
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Service\Microsoft.PowerToys.Run.Plugin.Service.deps.json" -fileListName ServiceComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName ServiceImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\Service\Images"
Generate-FileComponents -fileListName "ServiceComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ServiceImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ServiceComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "ServiceImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###System
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\System\Microsoft.PowerToys.Run.Plugin.System.deps.json" -fileListName SystemComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName SystemImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\System\Images"
Generate-FileComponents -fileListName "SystemComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SystemImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SystemComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "SystemImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###TimeDate
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\TimeDate\Microsoft.PowerToys.Run.Plugin.TimeDate.deps.json" -fileListName TimeDateComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName TimeDateImagesComponentFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\TimeDate\Images"
Generate-FileComponents -fileListName "TimeDateComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "TimeDateImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "TimeDateComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "TimeDateImagesComponentFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###WindowsSettings
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsSettings\Microsoft.PowerToys.Run.Plugin.WindowsSettings.deps.json" -fileListName WinSetCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName WinSetImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsSettings\Images"
Generate-FileComponents -fileListName "WinSetCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WinSetImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WinSetCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "WinSetImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###WindowsTerminal
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsTerminal\Microsoft.PowerToys.Run.Plugin.WindowsTerminal.deps.json" -fileListName WinTermCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName WinTermImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\WindowsTerminal\Images"
Generate-FileComponents -fileListName "WinTermCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WinTermImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WinTermCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "WinTermImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###PowerToys
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\PowerToys\Microsoft.PowerToys.Run.Plugin.PowerToys.deps.json" -fileListName PowerToysCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName PowerToysImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\PowerToys\Images"
Generate-FileComponents -fileListName "PowerToysCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "PowerToysImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "PowerToysCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "PowerToysImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
###ValueGenerator
Generate-FileList -fileDepsJson "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\ValueGenerator\Community.PowerToys.Run.Plugin.ValueGenerator.deps.json" -fileListName ValueGeneratorCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -isLauncherPlugin 1
Generate-FileList -fileDepsJson "" -fileListName ValueGeneratorImagesCmpFiles -wxsFilePath $PSScriptRoot\Run.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\RunPlugins\ValueGenerator\Images"
Generate-FileComponents -fileListName "ValueGeneratorCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ValueGeneratorCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
Generate-FileComponents -fileListName "ValueGeneratorImagesCmpFiles" -wxsFilePath $PSScriptRoot\Run.wxs
## Plugins
#ShortcutGuide
Generate-FileList -fileDepsJson "" -fileListName ShortcutGuideSvgFiles -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\ShortcutGuide\"
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs -regroot $registryroot
Generate-FileComponents -fileListName "ShortcutGuideSvgFiles" -wxsFilePath $PSScriptRoot\ShortcutGuide.wxs
#Settings
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\"
Generate-FileList -fileDepsJson "" -fileListName SettingsV2AssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Modules\"
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsModulesFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Modules\OOBE\"
Generate-FileList -fileDepsJson "" -fileListName SettingsV2OOBEAssetsFluentIconsFiles -wxsFilePath $PSScriptRoot\Settings.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\WinUI3Apps\Assets\Settings\Icons\"
Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs -regroot $registryroot
Generate-FileComponents -fileListName "SettingsV2AssetsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2AssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsModulesFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
Generate-FileComponents -fileListName "SettingsV2OOBEAssetsFluentIconsFiles" -wxsFilePath $PSScriptRoot\Settings.wxs
#Workspaces
Generate-FileList -fileDepsJson "" -fileListName WorkspacesImagesComponentFiles -wxsFilePath $PSScriptRoot\Workspaces.wxs -depsPath "$PSScriptRoot..\..\..\$platform\Release\Assets\Workspaces\"
Generate-FileComponents -fileListName "WorkspacesImagesComponentFiles" -wxsFilePath $PSScriptRoot\Workspaces.wxs -regroot $registryroot
Generate-FileComponents -fileListName "WorkspacesImagesComponentFiles" -wxsFilePath $PSScriptRoot\Workspaces.wxs

View File

@@ -26,6 +26,16 @@ namespace ManagedCommon
private static readonly string Version = Assembly.GetExecutingAssembly().GetCustomAttribute<AssemblyFileVersionAttribute>()?.Version ?? "Unknown";
/// <summary>
/// Gets the path to the log directory for the current version of the app.
/// </summary>
public static string CurrentVersionLogDirectoryPath { get; private set; }
/// <summary>
/// Gets the path to the log directory for the app.
/// </summary>
public static string AppLogDirectoryPath { get; private set; }
/// <summary>
/// Initializes the logger and sets the path for logging.
/// </summary>
@@ -42,6 +52,9 @@ namespace ManagedCommon
Directory.CreateDirectory(versionedPath);
}
AppLogDirectoryPath = basePath;
CurrentVersionLogDirectoryPath = versionedPath;
var logFilePath = Path.Combine(versionedPath, "Log_" + DateTime.Now.ToString(@"yyyy-MM-dd", CultureInfo.InvariantCulture) + ".log");
Trace.Listeners.Add(new TextWriterTraceListener(logFilePath));

View File

@@ -19,6 +19,7 @@ HANDLE g_ServiceStopEvent = nullptr;
extern int g_lastUpdatedDay = -1;
static ScheduleMode prevMode = ScheduleMode::Off;
static std::wstring prevLat, prevLon;
static int prevMinutes = -1;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR* argv);
VOID WINAPI ServiceCtrlHandler(DWORD dwCtrl);
@@ -149,7 +150,6 @@ static void update_sun_times(auto& settings)
std::wstring wmsg(e.what(), e.what() + strlen(e.what()));
Logger::error(L"[LightSwitchService] Exception during sun time update: {}", wmsg);
}
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
@@ -379,6 +379,7 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
update_sun_times(settings);
g_lastUpdatedDay = st.wDay;
prevMinutes = -1;
Logger::info(L"[LightSwitchService] Recalculated sun times at new day boundary.");
}
@@ -403,11 +404,36 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
if (manualOverrideActive)
{
if (nowMinutes == (currentSettings.lightTime + currentSettings.sunrise_offset) % 1440 ||
nowMinutes == (currentSettings.darkTime + currentSettings.sunset_offset) % 1440)
int lightBoundary = (currentSettings.lightTime + currentSettings.sunrise_offset) % 1440;
int darkBoundary = (currentSettings.darkTime + currentSettings.sunset_offset) % 1440;
bool crossedLight = false;
bool crossedDark = false;
if (prevMinutes != -1)
{
if (nowMinutes < prevMinutes)
{
crossedLight = (prevMinutes <= lightBoundary || nowMinutes >= lightBoundary);
crossedDark = (prevMinutes <= darkBoundary || nowMinutes >= darkBoundary);
}
else
{
crossedLight = (prevMinutes < lightBoundary && nowMinutes >= lightBoundary);
crossedDark = (prevMinutes < darkBoundary && nowMinutes >= darkBoundary);
}
}
Logger::debug(L"[LightSwitchService] prevMinutes={} nowMinutes={} light={} dark={}",
prevMinutes,
nowMinutes,
lightBoundary,
darkBoundary);
if (crossedLight || crossedDark)
{
ResetEvent(hManualOverride);
Logger::info(L"[LightSwitchService] Manual override cleared at boundary");
Logger::info(L"[LightSwitchService] Manual override cleared after crossing schedule boundary.");
}
else
{
@@ -430,6 +456,8 @@ DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
if (msToNextMinute < 50)
msToNextMinute = 50;
prevMinutes = nowMinutes;
DWORD wait = WaitForMultipleObjects(count, waits, FALSE, msToNextMinute);
if (wait == WAIT_OBJECT_0)
{

View File

@@ -40,6 +40,8 @@ namespace Microsoft.CmdPal.UI;
/// </summary>
public partial class App : Application
{
private readonly GlobalErrorHandler _globalErrorHandler = new();
/// <summary>
/// Gets the current <see cref="App"/> instance in use.
/// </summary>
@@ -61,6 +63,10 @@ public partial class App : Application
/// </summary>
public App()
{
#if !CMDPAL_DISABLE_GLOBAL_ERROR_HANDLER
_globalErrorHandler.Register(this);
#endif
Services = ConfigureServices();
this.InitializeComponent();

View File

@@ -0,0 +1,134 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using ManagedCommon;
using Microsoft.CmdPal.Core.Common.Helpers;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;
using SystemUnhandledExceptionEventArgs = System.UnhandledExceptionEventArgs;
using XamlUnhandledExceptionEventArgs = Microsoft.UI.Xaml.UnhandledExceptionEventArgs;
namespace Microsoft.CmdPal.UI.Helpers;
/// <summary>
/// Global error handler for Command Palette.
/// </summary>
internal sealed partial class GlobalErrorHandler
{
// GlobalErrorHandler is designed to be self-contained; it can be registered and invoked before a service provider is available.
internal void Register(App app)
{
ArgumentNullException.ThrowIfNull(app);
app.UnhandledException += App_UnhandledException;
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void App_UnhandledException(object sender, XamlUnhandledExceptionEventArgs e)
{
// Exceptions thrown on the main UI thread are handled here.
if (e.Exception != null)
{
HandleException(e.Exception, Context.MainThreadException);
}
}
private void CurrentDomain_UnhandledException(object sender, SystemUnhandledExceptionEventArgs e)
{
// Exceptions thrown on background threads are handled here.
if (e.ExceptionObject is Exception ex)
{
HandleException(ex, Context.AppDomainUnhandledException);
}
}
private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
{
// This event is raised only when a faulted Task is garbage-collected
// without its exception being observed. It is NOT raised immediately
// when the Task faults; timing depends on GC finalization.
e.SetObserved();
HandleException(e.Exception, Context.UnobservedTaskException, isRecoverable: true);
}
private void HandleException(Exception ex, Context context, bool isRecoverable = false)
{
Logger.LogError($"Unhandled exception detected ({context})", ex);
if (context == Context.MainThreadException)
{
var error = DiagnosticsHelper.BuildExceptionMessage(ex, null);
var report = $"""
This is an error report generated by Windows Command Palette.
If you are seeing this message, it means the application has encountered an unexpected issue.
You can help us fix it by filing a report at https://aka.ms/powerToysReportBug.
{error}
""";
StoreReport(report, storeOnDesktop: false);
PInvoke.MessageBox(
HWND.Null,
"Command Palette has encountered a fatal error and must close.\n\nAn error report has been saved to your desktop.",
"Unhandled Error",
MESSAGEBOX_STYLE.MB_ICONERROR);
}
}
private static string? StoreReport(string report, bool storeOnDesktop)
{
// Generate a unique name for the report file; include timestamp and a random zero-padded number to avoid collisions
// in case of crash storm.
var name = FormattableString.Invariant($"CmdPal_ErrorReport_{DateTime.Now:yyyy-MM-dd_HH-mm-ss}_{Random.Shared.Next(100000):D5}.log");
// Always store a copy in log directory, this way it is available for Bug Report Tool
string? reportPath = null;
if (Logger.CurrentVersionLogDirectoryPath != null)
{
reportPath = Save(report, name, static () => Logger.CurrentVersionLogDirectoryPath);
}
// Optionally store a copy on the desktop for user (in)convenience
if (storeOnDesktop)
{
var path = Save(report, name, static () => Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory));
// show the desktop copy if both succeeded
if (path != null)
{
reportPath = path;
}
}
return reportPath;
static string? Save(string reportContent, string reportFileName, Func<string> directory)
{
try
{
var logDirectory = directory();
Directory.CreateDirectory(logDirectory);
var reportFilePath = Path.Combine(logDirectory, reportFileName);
File.WriteAllText(reportFilePath, reportContent);
return reportFilePath;
}
catch (Exception ex)
{
Logger.LogError("Failed to store exception report", ex);
return null;
}
}
}
private enum Context
{
Unknown = 0,
MainThreadException,
BackgroundThreadException,
UnobservedTaskException,
AppDomainUnhandledException,
}
}

View File

@@ -110,7 +110,7 @@ public partial class BookmarkResolverTests
[
new PlaceholderClassificationCase(
Name: "Drive",
Input: "C:",
Input: "C:\\.",
ExpectSuccess: true,
ExpectedKind: CommandKind.Directory,
ExpectedTarget: "C:\\",