mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-10-28 16:44:58 +08:00
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? --> ## Summary of the Pull Request Add Workspaces **list** and synchronous **launch** through a thin native CLI and shared GUI/CLI execution core. Related to #49900; capture/create/CRUD are excluded. Usage and contracts: `doc\devdocs\modules\workspaces-cli.md`. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist - [ ] Closes: N/A - partial scope of #49900. <!-- - [ ] Closes: #yyy (add separate lines for additional resolved issues) --> - [x] **Communication:** I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass (scoped local runs below; CI/release gates remain) - [x] **Localization:** All end-user-facing strings can be localized - [x] **Dev docs:** Added/updated - [x] **New binaries:** Added on the required places - [x] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [x] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - current integration: `installer\PowerToysSetupVNext\CliShims.wxs` - [x] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - existing discovery; session-peer companion signing updated - [x] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - N/A: existing signing pipeline - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: N/A - follow-up not filed. <!-- Provide a more detailed description of the PR, other things fixed, or any additional comments/features here --> ## Detailed Description of the Pull Request / Additional comments ### Shared execution, conditional process boundary ```mermaid flowchart TB EDITOR["Editor process<br/>C# / WPF"] -->|"start GUI Launcher"| ADAPTER SHELL["Terminal / script"] -->|"CLI shim starts CLI"| ADAPTER subgraph CALLER["Caller process: CLI.exe OR Launcher.exe in GUI mode"] ADAPTER["Thin entry adapter"] START["WorkspacesSession::Start<br/>snapshot + context check"] LOCAL["WorkspacesSession::Execute()<br/>function inside the caller process"] ADAPTER -->|"in-process"| START START -->|"verified Medium: in-process"| LOCAL LOCAL -.->|"typed return via Start"| ADAPTER end subgraph HOST["Elevated callers only: Medium host process<br/>PowerToys.WorkspacesLauncher.exe"] HANDOFF["Host entry<br/>receive and validate SessionHandoff"] REMOTE["WorkspacesSession::Execute()<br/>function inside this host process"] HANDOFF -->|"function call within the same process"| REMOTE end START -->|"elevated: create host<br/>read-only snapshot + restricted handles"| HANDOFF REMOTE -.->|"private anonymous result pipe"| START START -.->|"host outcome returned"| ADAPTER LOCAL <-->|"named pipes"| ARRANGER["WindowArranger process"] REMOTE <-->|"named pipes"| ARRANGER LOCAL <-->|"named pipes"| UI["Existing WPF Launcher UI process"] REMOTE <-->|"named pipes"| UI classDef shared fill:#dbeafe,stroke:#2563eb,color:#172554 class START,LOCAL,REMOTE shared ``` The caller box represents **one of the two entry executables**, not both in one process. Blue nodes are code statically linked from `WorkspacesLib.lib`, not a DLL or shared service. **Medium GUI/CLI callers execute in their own process without another Launcher host.** Only elevated callers create a verified Medium host through the existing `run_non_elevated` helper; it calls the same `WorkspacesLib\LaunchExecution.cpp` core. No elevated fallback. **`Execute()` is a function, not another EXE.** The host entry and its `Execute()` share the same process ID. Execution uses a worker thread inside that process, not another Launcher process. The two `Execute()` nodes represent the same library implementation running in alternative caller/host contexts. - **Shared behavior:** one preparation, launch, arrangement, confirmation and history flow. GUI retains progress; CLI shows only required existing confirmation UI. GUI Cancel and console cancellation use the shared stop/result path; already-started apps survive. Arranger callbacks are stopped and joined before their helper owner is released. An unresponsive inline Shell call yields `outcomeUnknown` before the one-shot adapter exits, rather than killing a thread or claiming cancellation succeeded. - **Contracts:** `list` is read-only; summary JSON reuses existing names. All arranged = `completed`/0; partial progress = `partial`/10; no progress = `failed`/10. Incomplete, fractional or invalid final states yield `outcomeUnknown`/9. Persistence verification failure retains exit 11 and displays application results in both text and JSON modes. The existing `LaunchedAndMoved` enum and numeric IPC values are unchanged. - **Persistence/integration:** preserve IDs, initialize missing legacy IDs, update history best-effort; unsaved GUI drafts do not write saved configuration/history. Only shim `bin` goes on PATH. Editor sibling-tool resolution is executable-relative. - **Telemetry:** one frontend `Workspaces_CLICommand` event when optional diagnostics are enabled, following #50507's fixed command category + success model. No workspace names/IDs, paths, arguments or error text; the Medium host does not double-count. Uses the existing native telemetry channel; documented in `DATA_AND_PRIVACY.md`. - **Release IPC:** exact session-owner PID and official CLI/Launcher identities remain checked. CI companion signing now includes CLI, Launcher, arranger and Launcher UI; production signature checks are not disabled. - **Console isolation:** console workspace targets get their own console; inline execution does not detach, redirect or share the CLI's console. - **Launch and Edit:** a missing temporary draft now falls back to the saved workspace before GUID validation; malformed existing drafts still fail. The existing UI regression explicitly checks that no draft is present. - **GUI file errors:** unreadable saved files and drafts show the existing localized file-reading dialog with the correct source filename; malformed-file dialogs also retain that context. Public CLI error JSON is unchanged. - **UI-test transport:** shared value setters place target options before `--` and pass selectors/values literally. This fixes the leading-dash command-line inputs rejected by CI's winapp 0.7.1 without changing Workspaces test payloads or assertions. ### Changed-file breakdown Full PR versus main, not just the latest commit. Each file is counted once; test projects and fixtures are grouped under tests. These are file categories, not process or library boundaries. | Category | Files | |---|---:| | CLI adapter, output, resources and project | 7 | | Shared session/execution entry, contracts, IPC, storage and telemetry | 19 | | Launcher engine/host adapter, arranger and UI | 18 | | Managed storage and Editor path compatibility | 4 | | Common helpers | 9 | | Tests and fixtures | 24 | | Build, installer and signing | 6 | | Documentation and privacy catalog | 4 | | **Total** | **91** | The Launcher engine sources are compiled into `WorkspacesLib` even though their source files remain under `WorkspacesLauncher`; the table does not imply a separate engine process. **Scope/known follow-ups:** general Editor save/conflict redesign and the pre-existing localized-name/package-version matching bug are deferred. Final GUI progress presentation still needs follow-up; this update does not claim to fix its spinner-before-close behavior. The native C++ parser is retained by the PR author's decision; a managed System.CommandLine migration is not included. This does not amend the repository-wide CLI convention. <details> <summary>List output and shared confirmation UI</summary>   </details> <!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well --> ## Validation Steps Performed x64 Debug builds of the affected product and UI-test/fixture projects passed; Release core, ModuleInterface, arranger, Launcher and CLI builds also passed. The pre-GUI-error scoped native run passed **160 tests**. Two deterministic paused-dispatch regressions reproduced `0xC0000005` before the teardown fix (snapshot and final-result callbacks); both now return acknowledged cancellation. Test hooks are compiled only into the fixture, not production builds. **48 signing-selection** tests passed earlier against unchanged selection logic. The preceding missing-draft fix passed **39 focused tests** plus the complete local-host `winapp` Launch and Edit flow, with settings/pointer/Editor state restored. This is targeted host validation, not full local OS-matrix sign-off. The GUI error follow-up `8ea5619586` passed **33 focused native tests in each of Debug and Release**, including a regression that failed before the fix. Both real saved-file/draft error dialogs were driven locally with UIA; original configuration bytes and draft absence were restored. The CI transport follow-up `e0945376e6` passed **19 focused shared-harness tests in each of Debug and Release**. Using the hash-verified winapp **0.7.1** archive from the failing CI revision, the original invocation reproduced `invalid_arguments`; the fixed wrappers passed **nine owned-UI setter checks** for leading options, quoted text, empty text, and negative numeric values. The TextBox, editable ComboBox, NumberBox, and Slider setters share the corrected argument boundary. This is focused wrapper validation, not a claim that the full Workspaces suite ran locally. <details> <summary>Commands and results</summary> Used the verified side-by-side SDK 10.0.303; no global/repository SDK or package-source change. With `$root='D:\PowerToys-workspace-cli'`, from each affected project directory: ```powershell & "$root\tools\build\build.ps1" -Platform x64 -Configuration Debug -ExtraArgs @("/p:SolutionDir=$root\", '/p:BuildProjectReferences=false', '/p:WorkspacesCliLiveTests=true') # Passed, exit 0. & "$root\tools\build\build.ps1" -Platform x64 -Configuration Release -ExtraArgs @("/p:SolutionDir=$root\", '/p:BuildProjectReferences=false') # Passed, exit 0, for core/arranger/Launcher/CLI. ``` Missing Release UI dependencies were first built with project references enabled: ```powershell # From src\modules\Workspaces\WorkspacesLauncherUI: & "$root\tools\build\build.ps1" -Platform x64 -Configuration Release -ExtraArgs @("/p:SolutionDir=$root\") # Passed, exit 0. ``` Pre-GUI-error scoped native run (`$evidence` is the local report directory): ```powershell $env:WORKSPACES_CLI_LIVE_TESTS='1' & 'C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe' "$root\x64\Debug\tests\Workspaces\Workspaces.Lib.UnitTests.dll" '/TestCaseFilter:FullyQualifiedName~CliContractTests|FullyQualifiedName~CliJsonOutputTests|FullyQualifiedName~CliRuntimeTests|FullyQualifiedName~CliHandoffTests|FullyQualifiedName~CliWorkerTests|FullyQualifiedName~WorkspaceStoreTests|FullyQualifiedName~SignatureVerificationTests|FullyQualifiedName~SignatureTrustTests|FullyQualifiedName~ExecutableTargetTests|FullyQualifiedName~ElevatedLaunchGateTests|FullyQualifiedName~PendingLaunchApprovalTests' "/ResultsDirectory:$evidence" '/Logger:trx;LogFileName=teardown-race-green.trx' '/Logger:console;verbosity=minimal' # Passed: 160; failed/skipped: 0; exit 0. & 'C:\Program Files\Microsoft Visual Studio\18\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe' "$root\x64\Debug\tests\Workspaces\Workspaces.Lib.UnitTests.dll" '/TestCaseFilter:FullyQualifiedName~CliContractTests|FullyQualifiedName~JsonUtilsTests' "/ResultsDirectory:$evidence" '/Logger:trx;LogFileName=missing-draft-headless.trx' '/Logger:console;verbosity=minimal' # Passed after the draft fix: 39; failed/skipped: 0; exit 0. Invoke-Pester -Script 'D:\PowerToys-workspace-cli\.pipelines\tests\uiTestSigningSelection.Tests.ps1' -PassThru # Passed: 48; failed: 0. git diff --check # Passed, exit 0. ``` Telemetry lifecycle tests use a recording sink and synthetic commands; they neither transmit telemetry nor change diagnostic consent. Recorded host UI actions (3892 was this run's owned Editor PID, not a reusable PID): ```powershell winapp ui 'invoke' 'EditButton' '-a' '3892' '--json' winapp ui 'invoke' 'LaunchEditButton' '-a' '3892' '--json' winapp ui 'invoke' 'SnapshotButton' '-a' '3892' '--json' winapp ui 'invoke' 'SaveButton' '-a' '3892' '--json' # All passed, exit 0; fixture startup, exact placement, recapture and persisted IDs were asserted. ``` </details> Latest shared-harness build/test commands, from `src\common\UITestAutomation.Next.UnitTests`: ```powershell & "$root\tools\build\build.ps1" -Platform x64 -Configuration Debug -ExtraArgs @("/p:SolutionDir=$root\") & "$root\tools\build\build.ps1" -Platform x64 -Configuration Release -ExtraArgs @("/p:SolutionDir=$root\") # Both passed, exit 0, including analyzers. & "$root\x64\Debug\tests\UITestAutomation.Next.UnitTests\net10.0-windows10.0.26100.0\UITestAutomation.Next.UnitTests.exe" --filter 'FullyQualifiedName~WinappCliTests|FullyQualifiedName~SessionTests' --report-trx --report-trx-filename ci-set-value-unit.trx --results-directory $evidence & "$root\x64\Release\tests\UITestAutomation.Next.UnitTests\net10.0-windows10.0.26100.0\UITestAutomation.Next.UnitTests.exe" --filter 'FullyQualifiedName~WinappCliTests|FullyQualifiedName~SessionTests' --report-trx --report-trx-filename ci-set-value-unit-release.trx --results-directory $evidence # Each passed: 19; failed/skipped: 0; exit 0. ``` **CI status:** [391837](https://dev.azure.com/shine-oss/62769a65-d989-45e3-803c-9ad21fcf2ea2/_build/results?buildId=391837) **succeeded** on current head `e0945376e6`, tested as merge `e27f537028` with main `79ceeee01c`. SDK/x64/ARM64 builds passed, and **34/34 Workspaces UI tests passed on each of Windows 10 x64, Windows 11 x64, and Windows 11 ARM64**, with zero failures or skips. Finished 2026-10-26 16:18:46 UTC. The preceding [391820](https://dev.azure.com/shine-oss/62769a65-d989-45e3-803c-9ad21fcf2ea2/_build/results?buildId=391820) on `8ea5619586` passed product builds but had 29/34 UI tests pass on each platform. All five failures were leading-dash textbox values rejected by winapp 0.7.1; the shared helper was identical to main and predates this PR. The setter fix resolves those failures without changing Workspaces product code or weakening assertions. Fresh High-parent/UAC, installer servicing and broader mixed-DPI validation remain release gates. --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 664ee900-ce2d-4112-ac57-395314d818dc
PowerToys Modules
This section contains documentation for individual PowerToys modules, including their architecture, implementation details, and debugging tools.
Available Modules
| Module | Description |
|---|---|
| Advanced Paste | Tool for enhanced clipboard pasting with formatting options |
| Always on Top | Tool for pinning windows to stay on top of other windows |
| Awake | Tool to keep your computer awake without modifying power settings |
| Color Picker | Tool for selecting and managing colors from the screen |
| Command Not Found | Tool suggesting package installations for missing commands |
| Crop and Lock | Tool for cropping application windows into smaller windows or thumbnails |
| Environment Variables | Tool for managing user and system environment variables |
| FancyZones (debugging tools) | Window manager utility for custom window layouts |
| File Explorer add-ons | Extensions for enhancing Windows File Explorer functionality |
| File Locksmith | Tool for finding processes that lock files |
| Hosts File Editor | Tool for managing the system hosts file |
| Image Resizer | Tool for quickly resizing images within File Explorer |
| Keyboard Manager | Tool for remapping keys and keyboard shortcuts |
| Mouse Utilities | Collection of tools to enhance mouse and cursor functionality |
| Mouse Without Borders | Tool for controlling multiple computers with a single mouse and keyboard |
| NewPlus | Context menu extension for creating new files in File Explorer |
| Peek | File preview utility for quick file content viewing |
| Power Rename | Bulk file renaming tool with search and replace functionality |
| PowerToys Run (deprecation soon) | Quick application launcher and search utility |
| Quick Accent | Tool for quickly inserting accented characters and special symbols |
| Registry Preview | Tool for visualizing and editing Registry files |
| Screen Ruler | Tool for measuring pixel distances and color boundaries on screen |
| Shortcut Guide | Tool for displaying Windows keyboard shortcuts when holding the Windows key |
| Text Extractor | Tool for extracting text from images and screenshots |
| Window Hopper (Alt Window Cycle) | Tool for cycling between windows of the focused application |
| Workspaces | Tool for saving and restoring window layouts for different projects |
| ZoomIt | Screen zoom and annotation tool |
Adding New Module Documentation
When adding documentation for a new module:
- Create a dedicated markdown file for the module (e.g.,
modulename.md) - If the module has specialized debugging tools, consider creating a separate tools document (e.g.,
modulename-tools.md) - Update this index with links to the new documentation
- Follow the existing documentation structure for consistency