mirror of
https://github.com/microsoft/PowerToys.git
synced 2025-12-15 19:27:56 +01:00
Merge branch 'main' into shawn/CLIFileLockSmith
This commit is contained in:
3
.github/actions/spell-check/expect.txt
vendored
3
.github/actions/spell-check/expect.txt
vendored
@@ -773,6 +773,7 @@ INITGUID
|
||||
INITTOLOGFONTSTRUCT
|
||||
INLINEPREFIX
|
||||
inlines
|
||||
Inno
|
||||
INPC
|
||||
inproc
|
||||
INPUTHARDWARE
|
||||
@@ -1629,6 +1630,7 @@ SKIPOWNPROCESS
|
||||
sku
|
||||
SLGP
|
||||
sln
|
||||
slnx
|
||||
SMALLICON
|
||||
smartphone
|
||||
smileys
|
||||
@@ -1847,6 +1849,7 @@ UNCPRIORITY
|
||||
UNDNAME
|
||||
UNICODETEXT
|
||||
unins
|
||||
Uninstaller
|
||||
uninstalls
|
||||
Uniquifies
|
||||
unitconverter
|
||||
|
||||
@@ -192,14 +192,14 @@ jobs:
|
||||
displayName: Verify XAML formatting
|
||||
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln'
|
||||
displayName: Verify Nuget package versions for PowerToys.sln
|
||||
& '.pipelines/verifyNugetPackages.ps1' -solution '$(build.sourcesdirectory)\PowerToys.slnx'
|
||||
displayName: Verify Nuget package versions for PowerToys.slnx
|
||||
|
||||
- pwsh: |-
|
||||
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.sln'
|
||||
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\PowerToys.slnx'
|
||||
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\BugReportTool\BugReportTool.sln'
|
||||
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\tools\StylesReportTool\StylesReportTool.sln'
|
||||
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.sln'
|
||||
& '.pipelines/verifyArm64Configuration.ps1' -solution '$(build.sourcesdirectory)\installer\PowerToysSetup.slnx'
|
||||
displayName: Verify ARM64 configurations
|
||||
|
||||
- ${{ if eq(parameters.enablePackageCaching, true) }}:
|
||||
@@ -252,7 +252,7 @@ jobs:
|
||||
${{ else }}:
|
||||
displayName: Build PowerToys main project
|
||||
inputs:
|
||||
solution: 'PowerToys.sln'
|
||||
solution: 'PowerToys.slnx'
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore -graph
|
||||
@@ -275,7 +275,7 @@ jobs:
|
||||
displayName: Generate DSC artifacts for ARM64
|
||||
condition: and(succeeded(), eq(variables['BuildPlatform'], 'arm64'))
|
||||
inputs:
|
||||
solution: PowerToys.sln
|
||||
solution: PowerToys.slnx
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore
|
||||
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
command: restore
|
||||
feedsToUse: config
|
||||
configPath: nuget.config
|
||||
restoreSolution: PowerToys.sln
|
||||
restoreSolution: PowerToys.slnx
|
||||
restoreDirectory: '$(Build.SourcesDirectory)\packages'
|
||||
|
||||
# Build all UI test projects if no specific modules are specified
|
||||
@@ -129,4 +129,4 @@ jobs:
|
||||
- publish: $(JobOutputDirectory)
|
||||
artifact: $(JobOutputArtifactName)
|
||||
displayName: Publish UI Test artifacts
|
||||
condition: always()
|
||||
condition: always()
|
||||
|
||||
@@ -35,7 +35,7 @@ steps:
|
||||
- task: VSBuild@1
|
||||
displayName: Build Shared Support DLLs
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
solution: "**/installer/PowerToysSetup.slnx"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:PowerToysSetupCustomActionsVNext;SilentFilesInUseBAFunction
|
||||
@@ -74,7 +74,7 @@ steps:
|
||||
- task: VSBuild@1
|
||||
displayName: 💻 Build VNext MSI
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
solution: "**/installer/PowerToysSetup.slnx"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore
|
||||
@@ -91,7 +91,7 @@ steps:
|
||||
- task: VSBuild@1
|
||||
displayName: 👤 Build VNext MSI
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
solution: "**/installer/PowerToysSetup.slnx"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:PowerToysInstallerVNext
|
||||
@@ -142,7 +142,7 @@ steps:
|
||||
- task: VSBuild@1
|
||||
displayName: 💻 Build VNext Bootstrapper
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
solution: "**/installer/PowerToysSetup.slnx"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
-restore
|
||||
@@ -159,7 +159,7 @@ steps:
|
||||
- task: VSBuild@1
|
||||
displayName: 👤 Build VNext Bootstrapper
|
||||
inputs:
|
||||
solution: "**/installer/PowerToysSetup.sln"
|
||||
solution: "**/installer/PowerToysSetup.slnx"
|
||||
vsVersion: 17.0
|
||||
msbuildArgs: >-
|
||||
/t:PowerToysBootstrapperVNext
|
||||
|
||||
@@ -54,4 +54,13 @@ steps:
|
||||
feedsToUse: 'config'
|
||||
nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
|
||||
restoreSolution: '$(build.sourcesdirectory)\**\*.sln'
|
||||
includeNuGetOrg: false
|
||||
includeNuGetOrg: false
|
||||
|
||||
- task: NuGetCommand@2
|
||||
displayName: 'Restore NuGet packages (slnx)'
|
||||
inputs:
|
||||
command: 'restore'
|
||||
feedsToUse: 'config'
|
||||
nugetConfigPath: '$(build.sourcesdirectory)\nuget.config'
|
||||
restoreSolution: '$(build.sourcesdirectory)\**\*.slnx'
|
||||
includeNuGetOrg: false
|
||||
|
||||
1041
PowerToys.slnx
Normal file
1041
PowerToys.slnx
Normal file
File diff suppressed because it is too large
Load Diff
@@ -134,7 +134,7 @@ If you prefer, you can alternatively build prerequisite projects for the install
|
||||
|
||||
#### Locally compiling the installer
|
||||
|
||||
1. Open `installer\PowerToysSetup.sln`
|
||||
1. Open `installer\PowerToysSetup.slnx`
|
||||
1. In Visual Studio, in the `Solutions Configuration` drop-down menu select `Release`
|
||||
1. From the `Build` menu choose `Build Solution`.
|
||||
|
||||
@@ -144,9 +144,9 @@ To build the installer from the command line, run `Developer Command Prompt for
|
||||
|
||||
```
|
||||
git clean -xfd -e *exe -- .\installer\
|
||||
MSBuild -t:restore .\installer\PowerToysSetup.sln -p:RestorePackagesConfig=true /p:Platform="x64" /p:Configuration=Release
|
||||
MSBuild -t:Restore -m .\installer\PowerToysSetup.sln /t:PowerToysInstallerVNext /p:Configuration=Release /p:Platform="x64"
|
||||
MSBuild -t:Restore -m .\installer\PowerToysSetup.sln /t:PowerToysBootstrapperVNext /p:Configuration=Release /p:Platform="x64"
|
||||
MSBuild -t:restore .\installer\PowerToysSetup.slnx -p:RestorePackagesConfig=true /p:Platform="x64" /p:Configuration=Release
|
||||
MSBuild -t:Restore -m .\installer\PowerToysSetup.slnx /t:PowerToysInstallerVNext /p:Configuration=Release /p:Platform="x64"
|
||||
MSBuild -t:Restore -m .\installer\PowerToysSetup.slnx /t:PowerToysBootstrapperVNext /p:Configuration=Release /p:Platform="x64"
|
||||
```
|
||||
|
||||
### Supported arguments for the .EXE Bootstrapper installer
|
||||
|
||||
@@ -19,7 +19,7 @@ You can build the entire solution from the command line, which is sometimes fast
|
||||
2. Navigate to the repository root directory
|
||||
3. Run the following command(don't forget to set the correct platform):
|
||||
```pwsh
|
||||
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.sln /tl /p:NuGetInteractive="true"
|
||||
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.slnx /tl /p:NuGetInteractive="true"
|
||||
```
|
||||
4. This process should complete in approximately 13-14 minutes for a full build
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ Or reach out to "tools\build\BUILD-GUIDELINES.md"
|
||||
### Sample plain msbuild command
|
||||
```powershell
|
||||
# Restore:
|
||||
msbuild powertoys.sln -t:restore -p:configuration=debug -p:platform=x64 -m
|
||||
msbuild powertoys.slnx -t:restore -p:configuration=debug -p:platform=x64 -m
|
||||
|
||||
# Build powertoys sln
|
||||
msbuild powertoys.sln -p:configuration=debug -p:platform=x64 -m
|
||||
# Build powertoys slnx
|
||||
msbuild powertoys.slnx -p:configuration=debug -p:platform=x64 -m
|
||||
|
||||
# dotnet project
|
||||
msbuild src\settings-ui\Settings.UI\PowerToys.Settings.csproj -p:Platform=x64 -p:Configuration=Debug -m
|
||||
@@ -122,7 +122,7 @@ Similar for attach to managed code.
|
||||
|
||||
| Task | Command / Action | Notes |
|
||||
|------|------------------|-------|
|
||||
| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.sln` | Deep clean removes packages & build outputs |
|
||||
| Clean | `git clean -xdf` (careful) or `msbuild /t:Clean PowerToys.slnx` | Deep clean removes packages & build outputs |
|
||||
| Rebuild single project | `msbuild path\to\proj.vcxproj /t:Rebuild -p:Platform=x64 -p:Configuration=Debug` | Faster than whole solution |
|
||||
| Generate installer (rare in inner loop) | See `tools\build\build-installer.ps1` | Usually not needed for local debug |
|
||||
| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets |
|
||||
| Resource conversion errors | Re-run restore + build | Triggers custom PowerShell targets |
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
- Exit PowerToys if it's running.
|
||||
|
||||
- Open `PowerToys.sln` in Visual Studio and build the solution.
|
||||
- Open `PowerToys.slnx` in Visual Studio and build the solution.
|
||||
|
||||
- Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`).
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ The module provides a user interface for configuring settings in the PowerToys S
|
||||
### Building and Testing
|
||||
|
||||
1. Clone the repository: `git clone https://github.com/microsoft/PowerToys.git`
|
||||
2. Open PowerToys.sln in Visual Studio
|
||||
2. Open PowerToys.slnx in Visual Studio
|
||||
3. Select the Release configuration and build the solution
|
||||
4. Run PowerToys.exe from the output directory to test the module
|
||||
|
||||
|
||||
@@ -161,7 +161,7 @@ FancyZones is divided into several projects:
|
||||
```
|
||||
git clone https://github.com/microsoft/PowerToys.git
|
||||
```
|
||||
2. Open `PowerToys.sln` in Visual Studio
|
||||
2. Open `PowerToys.slnx` in Visual Studio
|
||||
3. Select the Release configuration and build the solution
|
||||
4. If you encounter build errors, try deleting the x64 output folder and rebuild
|
||||
|
||||
@@ -244,7 +244,7 @@ UI tests are implemented using [Windows Application Driver](https://github.com/m
|
||||
|
||||
- Exit PowerToys if it's running
|
||||
- Run WinAppDriver.exe from the installation directory. Skip this step if installed in the default directory (`C:\Program Files (x86)\Windows Application Driver`); in this case, it'll be launched automatically during tests.
|
||||
- Open `PowerToys.sln` in Visual Studio and build the solution.
|
||||
- Open `PowerToys.slnx` in Visual Studio and build the solution.
|
||||
- Run tests in the Test Explorer (`Test > Test Explorer` or `Ctrl+E, T`).
|
||||
|
||||
>Note: notifications or other application windows, that are shown above the window under test, can disrupt the testing process.
|
||||
|
||||
@@ -11,7 +11,7 @@ Keyboard Manager consists of two main components:
|
||||
## Development Environment Setup
|
||||
|
||||
1. Clone the PowerToys repository
|
||||
2. Open `PowerToys.sln` in Visual Studio
|
||||
2. Open `PowerToys.slnx` in Visual Studio
|
||||
3. Ensure all NuGet packages are restored
|
||||
4. Build the entire solution in Debug configuration
|
||||
|
||||
@@ -91,4 +91,4 @@ If you encounter issues with multiple instances, check the mutex logic in `Keybo
|
||||
|
||||
To debug both the Editor and Engine:
|
||||
1. Launch the Engine first in debug mode
|
||||
2. Attach the debugger to the Editor process when it starts
|
||||
2. Attach the debugger to the Editor process when it starts
|
||||
|
||||
@@ -92,7 +92,7 @@ The module’s settings are exposed in the PowerToys Settings UI. Options includ
|
||||
3. Build the solution:
|
||||
|
||||
```sh
|
||||
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.sln
|
||||
msbuild -restore -p:RestorePackagesConfig=true -p:Platform=ARM64 -m PowerToys.slnx
|
||||
```
|
||||
|
||||
> Note: This may take some time.
|
||||
|
||||
@@ -53,7 +53,7 @@ The Screen Ruler module consists of several components:
|
||||
|
||||
### Building
|
||||
|
||||
1. Open PowerToys.sln in Visual Studio
|
||||
1. Open PowerToys.slnx in Visual Studio
|
||||
2. In the Solutions Configuration drop-down menu, select Release or Debug
|
||||
3. From the Build menu, choose Build Solution
|
||||
4. The executable app for Screen Ruler is named PowerToys.MeasureToolUI.exe
|
||||
|
||||
@@ -19,7 +19,7 @@ Shortcut Guide is a PowerToy that displays an overlay of available keyboard shor
|
||||
## Build and Debug Instructions
|
||||
|
||||
### Build
|
||||
1. Open PowerToys.sln in Visual Studio
|
||||
1. Open PowerToys.slnx in Visual Studio
|
||||
2. Select Release or Debug in the Solutions Configuration drop-down menu
|
||||
3. From the Build menu, choose Build Solution
|
||||
4. The executable is named PowerToys.ShortcutGuide.exe
|
||||
|
||||
@@ -80,7 +80,7 @@ Once you've discussed your proposed feature/fix/etc. with a team member, and an
|
||||
|
||||
### Install Visual Studio dependencies
|
||||
|
||||
1. Open the `PowerToys.sln` file.
|
||||
1. Open the `PowerToys.slnx` file.
|
||||
1. If you see a dialog that says `install extra components` in the solution explorer pane, click `install`
|
||||
|
||||
### Get Submodules to compile
|
||||
@@ -93,7 +93,7 @@ We have submodules that need to be initialized before you can compile most parts
|
||||
|
||||
### Compiling Source Code
|
||||
|
||||
- Open `PowerToys.sln` in Visual Studio.
|
||||
- Open `PowerToys.slnx` in Visual Studio.
|
||||
- In the `Solutions Configuration` drop-down menu select `Release` or `Debug`.
|
||||
- From the `Build` menu choose `Build Solution`, or press <kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>b</kbd> on your keyboard.
|
||||
- The build process may take several minutes depending on your computer's performance. Once it completes, the PowerToys binaries will be in your repo under `x64\Release\`.
|
||||
@@ -107,10 +107,10 @@ Our installer is two parts, an EXE and an MSI. The EXE (Bootstrapper) contains
|
||||
|
||||
The installer can only be compiled in `Release` mode; steps 1 and 2 must be performed before the MSI can be compiled.
|
||||
|
||||
1. Compile `PowerToys.sln`. Instructions are listed above.
|
||||
1. Compile `PowerToys.slnx`. Instructions are listed above.
|
||||
1. Compile `BugReportTool.sln` tool. Path from root: `tools\BugReportTool\BugReportTool.sln` (details listed below)
|
||||
1. Compile `StylesReportTool.sln` tool. Path from root: `tools\StylesReportTool\StylesReportTool.sln` (details listed below)
|
||||
1. Compile `PowerToysSetup.sln` Path from root: `installer\PowerToysSetup.sln` (details listed below)
|
||||
1. Compile `PowerToysSetup.slnx` Path from root: `installer\PowerToysSetup.slnx` (details listed below)
|
||||
|
||||
See [Installer](core/installer.md) for more details on building and debugging the installer.
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.1.32414.318
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "spdlog", "..\src\logging\logging.vcxproj", "{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "..\src\common\logger\logger.vcxproj", "{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Version", "..\src\common\version\version.vcxproj", "{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "EtwTrace", "..\src\common\Telemetry\EtwTrace\EtwTrace.vcxproj", "{8F021B46-362B-485C-BFBA-CCF83E820CBD}"
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysInstallerVNext", "PowerToysSetupVNext\PowerToysInstallerVNext.wixproj", "{B6E94700-DF38-41F6-A3FD-18B69674AB1E}"
|
||||
EndProject
|
||||
Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "PowerToysBootstrapperVNext", "PowerToysSetupVNext\PowerToysBootstrapperVNext.wixproj", "{DA4E9744-80BE-424C-B0F5-AFD8757DB575}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PowerToysSetupCustomActionsVNext", "PowerToysSetupCustomActionsVNext\PowerToysSetupCustomActionsVNext.vcxproj", "{B3A354B0-1E54-4B55-A962-FB5AF9330C19}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SilentFilesInUseBAFunction", "PowerToysSetupVNext\SilentFilesInUseBA\SilentFilesInUseBAFunction.vcxproj", "{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM64 = Debug|ARM64
|
||||
Debug|x64 = Debug|x64
|
||||
Release|ARM64 = Release|ARM64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Debug|x64.Build.0 = Debug|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.ActiveCfg = Release|x64
|
||||
{7E1E3F13-2BD6-3F75-A6A7-873A2B55C60F}.Release|x64.Build.0 = Release|x64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Debug|x64.Build.0 = Debug|x64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.ActiveCfg = Release|x64
|
||||
{D9B8FC84-322A-4F9F-BBB9-20915C47DDFD}.Release|x64.Build.0 = Release|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Debug|x64.Build.0 = Debug|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.ActiveCfg = Release|x64
|
||||
{CC6E41AC-8174-4E8A-8D22-85DD7F4851DF}.Release|x64.Build.0 = Release|x64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Debug|x64.Build.0 = Debug|x64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.ActiveCfg = Release|x64
|
||||
{8F021B46-362B-485C-BFBA-CCF83E820CBD}.Release|x64.Build.0 = Release|x64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Debug|x64.Build.0 = Debug|x64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|x64.ActiveCfg = Release|x64
|
||||
{B6E94700-DF38-41F6-A3FD-18B69674AB1E}.Release|x64.Build.0 = Release|x64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|ARM64.Build.0 = Debug|ARM64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Debug|x64.Build.0 = Debug|x64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|x64.ActiveCfg = Release|x64
|
||||
{DA4E9744-80BE-424C-B0F5-AFD8757DB575}.Release|x64.Build.0 = Release|x64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Debug|x64.Build.0 = Debug|x64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|x64.ActiveCfg = Release|x64
|
||||
{B3A354B0-1E54-4B55-A962-FB5AF9330C19}.Release|x64.Build.0 = Release|x64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|ARM64.ActiveCfg = Debug|ARM64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Debug|x64.Build.0 = Debug|x64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|ARM64.ActiveCfg = Release|ARM64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|ARM64.Build.0 = Release|ARM64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|x64.ActiveCfg = Release|x64
|
||||
{F8B9F842-F5C3-4A2D-8C85-7F8B9E2B4F1D}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {B7A3DA30-D443-40FF-AC51-988AD41E3962}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
22
installer/PowerToysSetup.slnx
Normal file
22
installer/PowerToysSetup.slnx
Normal file
@@ -0,0 +1,22 @@
|
||||
<Solution>
|
||||
<Configurations>
|
||||
<Platform Name="ARM64" />
|
||||
<Platform Name="x64" />
|
||||
</Configurations>
|
||||
<Project Path="../src/common/logger/logger.vcxproj" Id="d9b8fc84-322a-4f9f-bbb9-20915c47ddfd">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="../src/common/Telemetry/EtwTrace/EtwTrace.vcxproj" Id="8f021b46-362b-485c-bfba-ccf83e820cbd" />
|
||||
<Project Path="../src/common/version/version.vcxproj" Id="cc6e41ac-8174-4e8a-8d22-85dd7f4851df" />
|
||||
<Project Path="../src/logging/logging.vcxproj" Id="7e1e3f13-2bd6-3f75-a6a7-873a2b55c60f">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="PowerToysSetupCustomActionsVNext/PowerToysSetupCustomActionsVNext.vcxproj" Id="b3a354b0-1e54-4b55-a962-fb5af9330c19">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
<Project Path="PowerToysSetupVNext/PowerToysBootstrapperVNext.wixproj" Type="b7dd6f7e-def8-4e67-b5b7-07ef123db6f0" />
|
||||
<Project Path="PowerToysSetupVNext/PowerToysInstallerVNext.wixproj" Type="b7dd6f7e-def8-4e67-b5b7-07ef123db6f0" />
|
||||
<Project Path="PowerToysSetupVNext/SilentFilesInUseBA/SilentFilesInUseBAFunction.vcxproj" Id="f8b9f842-f5c3-4a2d-8c85-7f8b9e2b4f1d">
|
||||
<Build Solution="Debug|ARM64" Project="false" />
|
||||
</Project>
|
||||
</Solution>
|
||||
@@ -135,8 +135,9 @@ public partial class App : Application
|
||||
try
|
||||
{
|
||||
var winget = new WinGetExtensionCommandsProvider();
|
||||
var callback = allApps.LookupApp;
|
||||
winget.SetAllLookup(callback);
|
||||
winget.SetAllLookup(
|
||||
query => allApps.LookupAppByPackageFamilyName(query, requireSingleMatch: true),
|
||||
query => allApps.LookupAppByProductCode(query, requireSingleMatch: true));
|
||||
services.AddSingleton<ICommandProvider>(winget);
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -58,7 +58,7 @@ public class AllAppsCommandProviderTests : AppsTestBase
|
||||
var provider = new AllAppsCommandProvider(page);
|
||||
|
||||
// Act
|
||||
var result = provider.LookupApp(string.Empty);
|
||||
var result = provider.LookupAppByDisplayName(string.Empty);
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
@@ -77,7 +77,7 @@ public class AllAppsCommandProviderTests : AppsTestBase
|
||||
await WaitForPageInitializationAsync();
|
||||
|
||||
// Act
|
||||
var result = provider.LookupApp("TestApp");
|
||||
var result = provider.LookupAppByDisplayName("TestApp");
|
||||
|
||||
// Assert
|
||||
Assert.IsNotNull(result);
|
||||
@@ -97,7 +97,7 @@ public class AllAppsCommandProviderTests : AppsTestBase
|
||||
await WaitForPageInitializationAsync();
|
||||
|
||||
// Act
|
||||
var result = provider.LookupApp("NonExistentApp");
|
||||
var result = provider.LookupAppByDisplayName("NonExistentApp");
|
||||
|
||||
// Assert
|
||||
Assert.IsNull(result);
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
using Microsoft.CmdPal.Ext.Apps.Programs;
|
||||
using Microsoft.CmdPal.Ext.Apps.Properties;
|
||||
using Microsoft.CmdPal.Ext.Apps.State;
|
||||
using Microsoft.CommandPalette.Extensions;
|
||||
@@ -66,7 +68,71 @@ public partial class AllAppsCommandProvider : CommandProvider
|
||||
|
||||
public override ICommandItem[] TopLevelCommands() => [_listItem, .. _page.GetPinnedApps()];
|
||||
|
||||
public ICommandItem? LookupApp(string displayName)
|
||||
public ICommandItem? LookupAppByPackageFamilyName(string packageFamilyName, bool requireSingleMatch)
|
||||
{
|
||||
if (string.IsNullOrEmpty(packageFamilyName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var items = _page.GetItems();
|
||||
List<ICommandItem> matches = [];
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is AppListItem appItem && string.Equals(packageFamilyName, appItem.App.PackageFamilyName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
matches.Add(item);
|
||||
if (!requireSingleMatch)
|
||||
{
|
||||
// Return early if we don't require uniqueness.
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requireSingleMatch && matches.Count == 1 ? matches[0] : null;
|
||||
}
|
||||
|
||||
public ICommandItem? LookupAppByProductCode(string productCode, bool requireSingleMatch)
|
||||
{
|
||||
if (string.IsNullOrEmpty(productCode))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!UninstallRegistryAppLocator.TryGetInstallInfo(productCode, out _, out var candidates) || candidates.Count <= 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var items = _page.GetItems();
|
||||
List<ICommandItem> matches = [];
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is not AppListItem appListItem || string.IsNullOrEmpty(appListItem.App.FullExecutablePath))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
if (string.Equals(appListItem.App.FullExecutablePath, candidate, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
matches.Add(item);
|
||||
if (!requireSingleMatch)
|
||||
{
|
||||
return item;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return requireSingleMatch && matches.Count == 1 ? matches[0] : null;
|
||||
}
|
||||
|
||||
public ICommandItem? LookupAppByDisplayName(string displayName)
|
||||
{
|
||||
var items = _page.GetItems();
|
||||
|
||||
|
||||
@@ -29,6 +29,10 @@ public sealed class AppItem
|
||||
|
||||
public string AppIdentifier { get; set; } = string.Empty;
|
||||
|
||||
public string? PackageFamilyName { get; set; }
|
||||
|
||||
public string? FullExecutablePath { get; set; }
|
||||
|
||||
public AppItem()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ public sealed partial class AppListItem : ListItem
|
||||
|
||||
public string AppIdentifier => _app.AppIdentifier;
|
||||
|
||||
public AppItem App => _app;
|
||||
|
||||
public AppListItem(AppItem app, bool useThumbnails, bool isPinned)
|
||||
{
|
||||
Command = _appCommand = new AppCommand(app);
|
||||
@@ -82,6 +84,12 @@ public sealed partial class AppListItem : ListItem
|
||||
metadata.Add(new DetailsElement() { Key = "Path", Data = new DetailsLink() { Text = _app.ExePath } });
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
metadata.Add(new DetailsElement() { Key = "[DEBUG] AppIdentifier", Data = new DetailsLink() { Text = _app.AppIdentifier } });
|
||||
metadata.Add(new DetailsElement() { Key = "[DEBUG] ExePath", Data = new DetailsLink() { Text = _app.ExePath } });
|
||||
metadata.Add(new DetailsElement() { Key = "[DEBUG] IcoPath", Data = new DetailsLink() { Text = _app.IcoPath } });
|
||||
#endif
|
||||
|
||||
// Icon
|
||||
IconInfo? heroImage = null;
|
||||
if (_app.IsPackaged)
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
// 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 System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Microsoft.Win32;
|
||||
|
||||
namespace Microsoft.CmdPal.Ext.Apps.Helpers;
|
||||
|
||||
internal static class UninstallRegistryAppLocator
|
||||
{
|
||||
private static readonly string[] UninstallBaseKeys =
|
||||
[
|
||||
@"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
|
||||
@"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall",
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Tries to find install directory and a list of plausible main EXEs from an uninstall key
|
||||
/// (e.g. Inno Setup keys like "{guid}_is1").
|
||||
/// <paramref name="exeCandidates"/> may be empty if we couldn't pick any safe EXEs.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// Returns true if the uninstall key is found and an install directory is resolved.
|
||||
/// </returns>
|
||||
public static bool TryGetInstallInfo(
|
||||
string uninstallKeyName,
|
||||
out string? installDir,
|
||||
out IReadOnlyList<string> exeCandidates,
|
||||
string? expectedExeName = null)
|
||||
{
|
||||
installDir = null;
|
||||
exeCandidates = [];
|
||||
|
||||
if (string.IsNullOrWhiteSpace(uninstallKeyName))
|
||||
{
|
||||
throw new ArgumentException("Key name must not be null or empty.", nameof(uninstallKeyName));
|
||||
}
|
||||
|
||||
uninstallKeyName = uninstallKeyName.Trim();
|
||||
|
||||
foreach (var baseKeyPath in UninstallBaseKeys)
|
||||
{
|
||||
// HKLM
|
||||
using (var key = Registry.LocalMachine.OpenSubKey($"{baseKeyPath}\\{uninstallKeyName}"))
|
||||
{
|
||||
if (TryFromUninstallKey(key, expectedExeName, out installDir, out exeCandidates))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// HKCU
|
||||
using (var key = Registry.CurrentUser.OpenSubKey($"{baseKeyPath}\\{uninstallKeyName}"))
|
||||
{
|
||||
if (TryFromUninstallKey(key, expectedExeName, out installDir, out exeCandidates))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool TryFromUninstallKey(
|
||||
RegistryKey? key,
|
||||
string? expectedExeName,
|
||||
out string? installDir,
|
||||
out IReadOnlyList<string> exeCandidates)
|
||||
{
|
||||
installDir = null;
|
||||
exeCandidates = [];
|
||||
|
||||
if (key is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var location = (key.GetValue("InstallLocation") as string)?.Trim('"', ' ', '\t');
|
||||
if (string.IsNullOrEmpty(location))
|
||||
{
|
||||
location = (key.GetValue("Inno Setup: App Path") as string)?.Trim('"', ' ', '\t');
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(location))
|
||||
{
|
||||
var uninstall = key.GetValue("UninstallString") as string;
|
||||
var uninsExe = ExtractFirstPath(uninstall);
|
||||
if (!string.IsNullOrEmpty(uninsExe))
|
||||
{
|
||||
var dir = Path.GetDirectoryName(uninsExe);
|
||||
if (!string.IsNullOrEmpty(dir) && Directory.Exists(dir))
|
||||
{
|
||||
location = dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(location) || !Directory.Exists(location))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
installDir = location;
|
||||
|
||||
// Collect safe EXE candidates; may be empty if ambiguous or only uninstall exes exist.
|
||||
exeCandidates = GetExeCandidates(location, expectedExeName);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<string> GetExeCandidates(string root, string? expectedExeName)
|
||||
{
|
||||
// Look at root and a "bin" subfolder (very common pattern)
|
||||
var allExes = Directory.EnumerateFiles(root, "*.exe", SearchOption.TopDirectoryOnly)
|
||||
.Concat(GetBinExes(root))
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToArray();
|
||||
|
||||
if (allExes.Length == 0)
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
var result = new List<string>();
|
||||
|
||||
// 1) Exact match on expected exe name (if provided), ignoring case, and not uninstall/setup-like.
|
||||
if (!string.IsNullOrWhiteSpace(expectedExeName))
|
||||
{
|
||||
foreach (var exe in allExes)
|
||||
{
|
||||
if (string.Equals(Path.GetFileName(exe), expectedExeName, StringComparison.OrdinalIgnoreCase) &&
|
||||
!LooksLikeUninstallerOrSetup(exe))
|
||||
{
|
||||
result.Add(exe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2) All other non-uninstall/setup exes
|
||||
foreach (var exe in allExes)
|
||||
{
|
||||
if (LooksLikeUninstallerOrSetup(exe))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip ones already added as expectedExeName matches
|
||||
if (result.Contains(exe, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(exe);
|
||||
}
|
||||
|
||||
// 3) We intentionally do NOT add uninstall/setup/update exes here.
|
||||
// If you ever want them, you can add a separate API to expose them.
|
||||
return result;
|
||||
}
|
||||
|
||||
private static IEnumerable<string> GetBinExes(string root)
|
||||
{
|
||||
var bin = Path.Combine(root, "bin");
|
||||
return !Directory.Exists(bin)
|
||||
? []
|
||||
: Directory.EnumerateFiles(bin, "*.exe", SearchOption.TopDirectoryOnly);
|
||||
}
|
||||
|
||||
private static bool LooksLikeUninstallerOrSetup(string path)
|
||||
{
|
||||
var name = Path.GetFileName(path);
|
||||
return name.StartsWith("unins", StringComparison.OrdinalIgnoreCase) // e.g. Inno: unins000.exe
|
||||
|| name.Contains("setup", StringComparison.OrdinalIgnoreCase) // setup.exe
|
||||
|| name.Contains("installer", StringComparison.OrdinalIgnoreCase) // installer.exe / MyAppInstaller.exe
|
||||
|| name.Contains("update", StringComparison.OrdinalIgnoreCase); // updater/updater.exe
|
||||
}
|
||||
|
||||
private static string? ExtractFirstPath(string? commandLine)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(commandLine))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
commandLine = commandLine.Trim();
|
||||
|
||||
if (commandLine.StartsWith('"'))
|
||||
{
|
||||
var endQuote = commandLine.IndexOf('"', 1);
|
||||
if (endQuote > 1)
|
||||
{
|
||||
return commandLine[1..endQuote];
|
||||
}
|
||||
}
|
||||
|
||||
var firstSpace = commandLine.IndexOf(' ');
|
||||
var candidate = firstSpace > 0 ? commandLine[..firstSpace] : commandLine;
|
||||
candidate = candidate.Trim('"');
|
||||
return candidate.Length > 0 ? candidate : null;
|
||||
}
|
||||
}
|
||||
@@ -558,6 +558,7 @@ public class UWPApplication : IUWPApplication
|
||||
IsPackaged = true,
|
||||
Commands = app.GetCommands(),
|
||||
AppIdentifier = app.GetAppIdentifier(),
|
||||
PackageFamilyName = app.Package.FamilyName,
|
||||
};
|
||||
return item;
|
||||
}
|
||||
|
||||
@@ -1065,6 +1065,7 @@ public class Win32Program : IProgram
|
||||
DirPath = app.Location,
|
||||
Commands = app.GetCommands(),
|
||||
AppIdentifier = app.GetAppIdentifier(),
|
||||
FullExecutablePath = app.FullPath,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public partial class InstallPackageCommand : InvokableCommand
|
||||
{
|
||||
PackageInstallCommandState.Install => Icons.DownloadIcon,
|
||||
PackageInstallCommandState.Update => Icons.UpdateIcon,
|
||||
PackageInstallCommandState.Uninstall => Icons.CompletedIcon,
|
||||
PackageInstallCommandState.Uninstall => Icons.DeleteIcon,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
Name = InstallCommandState switch
|
||||
|
||||
@@ -194,46 +194,95 @@ public partial class InstallPackageListItem : ListItem
|
||||
var isInstalled = _package.InstalledVersion is not null;
|
||||
|
||||
var installedState = isInstalled ?
|
||||
(_package.IsUpdateAvailable ?
|
||||
PackageInstallCommandState.Update : PackageInstallCommandState.Uninstall) :
|
||||
(_package.IsUpdateAvailable ? PackageInstallCommandState.Update : PackageInstallCommandState.Uninstall) :
|
||||
PackageInstallCommandState.Install;
|
||||
|
||||
// might be an uninstall command
|
||||
InstallPackageCommand installCommand = new(_package, installedState);
|
||||
|
||||
if (isInstalled)
|
||||
if (_package.InstalledVersion is not null)
|
||||
{
|
||||
this.Icon = installCommand.Icon;
|
||||
this.Command = new NoOpCommand();
|
||||
#if DEBUG
|
||||
var installerType = _package.InstalledVersion.GetMetadata(PackageVersionMetadataField.InstallerType);
|
||||
Subtitle = installerType + " | " + Subtitle;
|
||||
#endif
|
||||
|
||||
List<IContextItem> contextMenu = [];
|
||||
CommandContextItem uninstallContextItem = new(installCommand)
|
||||
Command = installCommand;
|
||||
Icon = installedState switch
|
||||
{
|
||||
IsCritical = true,
|
||||
Icon = Icons.DeleteIcon,
|
||||
PackageInstallCommandState.Install => Icons.DownloadIcon,
|
||||
PackageInstallCommandState.Update => Icons.UpdateIcon,
|
||||
PackageInstallCommandState.Uninstall => Icons.CompletedIcon,
|
||||
_ => Icons.DownloadIcon,
|
||||
};
|
||||
|
||||
if (WinGetStatics.AppSearchCallback is not null)
|
||||
TryLocateAndAppendActionForApp(contextMenu);
|
||||
|
||||
MoreCommands = contextMenu.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
_installCommand = new InstallPackageCommand(_package, installedState);
|
||||
_installCommand.InstallStateChanged += InstallStateChangedHandler;
|
||||
Command = _installCommand;
|
||||
Icon = _installCommand.Icon;
|
||||
}
|
||||
}
|
||||
|
||||
private void TryLocateAndAppendActionForApp(List<IContextItem> contextMenu)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Let's try to connect it to an installed app if possible
|
||||
// This is a bit of dark magic, since there's no direct link between
|
||||
// WinGet packages and installed apps.
|
||||
var lookupByPackageName = WinGetStatics.AppSearchByPackageFamilyNameCallback;
|
||||
if (lookupByPackageName is not null)
|
||||
{
|
||||
var callback = WinGetStatics.AppSearchCallback;
|
||||
var installedApp = callback(_package.DefaultInstallVersion is null ? _package.Name : _package.DefaultInstallVersion.DisplayName);
|
||||
if (installedApp is not null)
|
||||
var names = _package.InstalledVersion.PackageFamilyNames;
|
||||
for (var i = 0; i < names.Count; i++)
|
||||
{
|
||||
this.Command = installedApp.Command;
|
||||
contextMenu = [.. installedApp.MoreCommands];
|
||||
var installedAppByPfn = lookupByPackageName(names[i]);
|
||||
if (installedAppByPfn is not null)
|
||||
{
|
||||
contextMenu.Add(new Separator());
|
||||
contextMenu.Add(new CommandContextItem(installedAppByPfn.Command));
|
||||
foreach (var item in installedAppByPfn.MoreCommands)
|
||||
{
|
||||
contextMenu.Add(item);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
contextMenu.Add(uninstallContextItem);
|
||||
this.MoreCommands = contextMenu.ToArray();
|
||||
return;
|
||||
var lookupByProductCode = WinGetStatics.AppSearchByProductCodeCallback;
|
||||
if (lookupByProductCode is not null)
|
||||
{
|
||||
var productCodes = _package.InstalledVersion.ProductCodes;
|
||||
for (var i = 0; i < productCodes.Count; i++)
|
||||
{
|
||||
var installedAppByProductCode = lookupByProductCode(productCodes[i]);
|
||||
if (installedAppByProductCode is not null)
|
||||
{
|
||||
contextMenu.Add(new Separator());
|
||||
contextMenu.Add(new CommandContextItem(installedAppByProductCode.Command));
|
||||
foreach (var item in installedAppByProductCode.MoreCommands)
|
||||
{
|
||||
contextMenu.Add(item);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Failed to retrieve app context menu items for package '{_package?.Name ?? "Unknown"}'", ex);
|
||||
}
|
||||
|
||||
// didn't find the app
|
||||
_installCommand = new InstallPackageCommand(_package, installedState);
|
||||
this.Command = _installCommand;
|
||||
|
||||
Icon = _installCommand.Icon;
|
||||
_installCommand.InstallStateChanged += InstallStateChangedHandler;
|
||||
}
|
||||
|
||||
private void InstallStateChangedHandler(object? sender, InstallPackageCommand e)
|
||||
|
||||
@@ -41,5 +41,9 @@ public partial class WinGetExtensionCommandsProvider : CommandProvider
|
||||
|
||||
public override void InitializeWithHost(IExtensionHost host) => WinGetExtensionHost.Instance.Initialize(host);
|
||||
|
||||
public void SetAllLookup(Func<string, ICommandItem?> callback) => WinGetStatics.AppSearchCallback = callback;
|
||||
public void SetAllLookup(Func<string, ICommandItem?> lookupByPackageName, Func<string, ICommandItem?> lookupByProductCode)
|
||||
{
|
||||
WinGetStatics.AppSearchByPackageFamilyNameCallback = lookupByPackageName;
|
||||
WinGetStatics.AppSearchByProductCodeCallback = lookupByProductCode;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,9 @@ internal static class WinGetStatics
|
||||
|
||||
private static readonly StatusMessage _errorMessage = new() { State = MessageState.Error };
|
||||
|
||||
public static Func<string, ICommandItem?>? AppSearchCallback { get; set; }
|
||||
public static Func<string, ICommandItem?>? AppSearchByPackageFamilyNameCallback { get; set; }
|
||||
|
||||
public static Func<string, ICommandItem?>? AppSearchByProductCodeCallback { get; set; }
|
||||
|
||||
private static readonly CompositeFormat CreateCatalogErrorMessage = System.Text.CompositeFormat.Parse(Properties.Resources.winget_create_catalog_error);
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ if ($IsAzurePipelineBuild) {
|
||||
}
|
||||
|
||||
if (($BuildStep -ieq "all") -Or ($BuildStep -ieq "build")) {
|
||||
& $nugetPath restore (Join-Path $PSScriptRoot "..\..\..\..\..\PowerToys.sln")
|
||||
& $nugetPath restore (Join-Path $PSScriptRoot "..\..\..\..\..\PowerToys.slnx")
|
||||
|
||||
Try {
|
||||
foreach ($config in $Configuration.Split(",")) {
|
||||
|
||||
@@ -12,7 +12,7 @@ Tip: Add `D:\PowerToys\tools\build` to your PATH to use the wrappers anywhere.
|
||||
|
||||
## When to use which
|
||||
1) `build-essentials.ps1`
|
||||
- Restores NuGet for `PowerToys.sln` and builds essentials (runner, settings).
|
||||
- Restores NuGet for `PowerToys.slnx` and builds essentials (runner, settings).
|
||||
- Auto-detects Platform; initializes VS Dev environment automatically.
|
||||
- Example (PowerShell):
|
||||
- `./tools/build/build-essentials.ps1`
|
||||
|
||||
@@ -113,7 +113,7 @@ function BuildProjectsInDirectory {
|
||||
|
||||
$files = @()
|
||||
try {
|
||||
$files = Get-ChildItem -Path (Join-Path $DirectoryPath '*') -Include *.sln,*.csproj,*.vcxproj -File -ErrorAction SilentlyContinue
|
||||
$files = Get-ChildItem -Path (Join-Path $DirectoryPath '*') -Include *.sln,*.slnx,*.csproj,*.vcxproj -File -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
$files = @()
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Build essential native PowerToys projects (runner and settings), restoring NuGet packages first.
|
||||
|
||||
.DESCRIPTION
|
||||
Lightweight script to build a small set of essential C++ projects used by PowerToys' runner and native modules. This script first restores NuGet packages for the full solution (`PowerToys.sln`) and then builds the runner and settings projects. Intended for fast local builds during development.
|
||||
Lightweight script to build a small set of essential C++ projects used by PowerToys' runner and native modules. This script first restores NuGet packages for the full solution (`PowerToys.slnx`) and then builds the runner and settings projects. Intended for fast local builds during development.
|
||||
|
||||
.PARAMETER Platform
|
||||
Target platform for the build (for example: 'x64', 'arm64'). If omitted the script will attempt to auto-detect the host platform.
|
||||
@@ -21,7 +21,7 @@ Restores packages and builds the essentials in Release mode for ARM64, even if y
|
||||
|
||||
.NOTES
|
||||
- This script dot-sources `build-common.ps1` and uses the shared helper `RunMSBuild`.
|
||||
- It will call `RestoreThenBuild 'PowerToys.sln'` before building the essential projects to ensure NuGet packages are restored.
|
||||
- It will call `RestoreThenBuild 'PowerToys.slnx'` before building the essential projects to ensure NuGet packages are restored.
|
||||
- The script attempts to locate the repository root automatically and can be run from any folder inside the repo.
|
||||
#>
|
||||
|
||||
@@ -33,7 +33,7 @@ param (
|
||||
# Find repository root starting from the script location
|
||||
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
|
||||
$repoRoot = $ScriptDir
|
||||
while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.sln"))) {
|
||||
while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) {
|
||||
$parent = Split-Path -Parent $repoRoot
|
||||
if ($parent -eq $repoRoot) {
|
||||
Write-Error "Could not find PowerToys repository root."
|
||||
@@ -63,7 +63,7 @@ if (-not $Platform -or $Platform -eq '') {
|
||||
}
|
||||
|
||||
# Ensure solution packages are restored
|
||||
RestoreThenBuild 'PowerToys.sln' '' $Platform $Configuration $true
|
||||
RestoreThenBuild 'PowerToys.slnx' '' $Platform $Configuration $true
|
||||
|
||||
# Build both runner and settings
|
||||
$ProjectsToBuild = @(".\src\runner\runner.vcxproj", ".\src\settings-ui\Settings.UI\PowerToys.Settings.csproj")
|
||||
@@ -71,4 +71,4 @@ $ExtraArgs = "/p:SolutionDir=$repoRoot\"
|
||||
foreach ($proj in $ProjectsToBuild) {
|
||||
Write-Host ("[BUILD-ESSENTIALS] Building {0}" -f $proj)
|
||||
RunMSBuild $proj $ExtraArgs $Platform $Configuration
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,18 +73,18 @@ $repoRoot = $scriptDir
|
||||
|
||||
# Navigate up from the script location to find the repo root
|
||||
# Script is typically in tools\build, so go up two levels
|
||||
while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.sln"))) {
|
||||
while ($repoRoot -and -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) {
|
||||
$parentDir = Split-Path -Parent $repoRoot
|
||||
if ($parentDir -eq $repoRoot) {
|
||||
# Reached the root of the drive, PowerToys.sln not found
|
||||
# Reached the root of the drive, PowerToys.slnx not found
|
||||
Write-Error "Could not find PowerToys repository root. Make sure this script is in the PowerToys repository."
|
||||
exit 1
|
||||
}
|
||||
$repoRoot = $parentDir
|
||||
}
|
||||
|
||||
if (-not $repoRoot -or -not (Test-Path (Join-Path $repoRoot "PowerToys.sln"))) {
|
||||
Write-Error "Could not locate PowerToys.sln. Please ensure this script is run from within the PowerToys repository."
|
||||
if (-not $repoRoot -or -not (Test-Path (Join-Path $repoRoot "PowerToys.slnx"))) {
|
||||
Write-Error "Could not locate PowerToys.slnx. Please ensure this script is run from within the PowerToys repository."
|
||||
exit 1
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ if (Test-Path $cmdpalOutputPath) {
|
||||
|
||||
$commonArgs = '/p:CIBuild=true'
|
||||
# No local projects found (or continuing) - build full solution and tools
|
||||
RestoreThenBuild 'PowerToys.sln' $commonArgs $Platform $Configuration
|
||||
RestoreThenBuild 'PowerToys.slnx' $commonArgs $Platform $Configuration
|
||||
|
||||
$msixSearchRoot = Join-Path $repoRoot "$Platform\$Configuration"
|
||||
$msixFiles = Get-ChildItem -Path $msixSearchRoot -Recurse -Filter *.msix |
|
||||
@@ -141,10 +141,10 @@ try {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "$commonArgs /t:restore /p:RestorePackagesConfig=true" $Platform $Configuration
|
||||
RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /t:restore /p:RestorePackagesConfig=true" $Platform $Configuration
|
||||
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "$commonArgs /m /t:PowerToysInstallerVNext /p:PerUser=$PerUser" $Platform $Configuration
|
||||
RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /m /t:PowerToysInstallerVNext /p:PerUser=$PerUser" $Platform $Configuration
|
||||
|
||||
RunMSBuild 'installer\PowerToysSetup.sln' "$commonArgs /m /t:PowerToysBootstrapperVNext /p:PerUser=$PerUser" $Platform $Configuration
|
||||
RunMSBuild 'installer\PowerToysSetup.slnx' "$commonArgs /m /t:PowerToysBootstrapperVNext /p:PerUser=$PerUser" $Platform $Configuration
|
||||
|
||||
Write-Host '[PIPELINE] Completed'
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
- The template will be available in Visual Studio, when adding a new project, under the `Visual C++` tab.
|
||||
|
||||
## Contributing
|
||||
If you'd like to work on a PowerToy template, make required modifications to `\tools\project_template\ModuleTemplate.vcxproj` and then use the dedicated solution `PowerToyTemplate.sln` to export it as a template. Note that `ModuleTemplate.vcxproj` is actually a project template, therefore uncompilable, so we also have a dedicated `ModuleTemplateCompileTest.vcxproj` project referenced from the `PowerToys.sln` to help keeping the template sources up to date and verify it compiles correctly.
|
||||
If you'd like to work on a PowerToy template, make required modifications to `\tools\project_template\ModuleTemplate.vcxproj` and then use the dedicated solution `PowerToyTemplate.sln` to export it as a template. Note that `ModuleTemplate.vcxproj` is actually a project template, therefore uncompilable, so we also have a dedicated `ModuleTemplateCompileTest.vcxproj` project referenced from the `PowerToys.slnx` to help keeping the template sources up to date and verify it compiles correctly.
|
||||
|
||||
## Create a new PowerToy Module
|
||||
|
||||
@@ -442,7 +442,7 @@ void ExamplePowertoy::save_settings() {
|
||||
|
||||
## Add a new PowerToy to the Installer
|
||||
|
||||
In the `installer` folder, open the `PowerToysSetup.sln` solution.
|
||||
In the `installer` folder, open the `PowerToysSetup.slnx` solution.
|
||||
Under the `PowerToysSetup` project, edit `Product.wxs`.
|
||||
You will need to add a component for your module DLL. Search for `Module_ShortcutGuide` to see where to add the component declaration and where to reference that declaration so the DLL is added to the installer.
|
||||
Each component requires a newly generated GUID (you can use the Visual Studio integrated tool to generate one).
|
||||
|
||||
Reference in New Issue
Block a user