<!-- 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
Microsoft PowerToys
Microsoft PowerToys is a collection of utilities that help you customize Windows and streamline everyday tasks.
Installation · Documentation · Blog · Release notes
🔨 Utilities
PowerToys includes over 30 utilities to help you customize and optimize your Windows experience:
📦 Installation
For detailed installation instructions and system requirements, visit the installation docs.
But to get started quickly, choose one of the installation methods below:
Download the .exe file from GitHub
Go to the PowerToys GitHub releases, scroll down and select Assets to reveal the installation files, and choose the one that matches your architecture and install scope. For most devices, that would be x64 per-user.
WinGet
Download PowerToys from [WinGet](https://github.com/microsoft/winget-cli#installing-the-client). Updating PowerToys via winget will respect the current PowerToys installation scope. To install PowerToys, run the following command from the command line / PowerShell:
- User scope installer (default)
winget install Microsoft.PowerToys -s winget
- Machine-wide scope installer
winget install --scope machine Microsoft.PowerToys -s winget
Other methods
There are [community driven install methods](https://learn.microsoft.com/windows/powertoys/install#community-driven-install-tools) such as Chocolatey and Scoop. If these are your preferred install solutions, you can find the install instructions there.
✨ What's new?
To see what's new, check out the release notes.
🛣️ Roadmap
For v0.103, we're working on a new Awake flyout, improving Screen Ruler, and continuing to modernize more utilities with WinUI 3.
❤️ PowerToys Community
The PowerToys team is extremely grateful to have the support of an amazing active community. The work you do is incredibly important. PowerToys wouldn't be nearly what it is today without your help filing bugs, updating documentation, guiding the design, or writing features. We want to say thank you and take time to recognize your work. Your contributions and feedback improve PowerToys month after month!
Contributing
This project welcomes contributions of all types. Besides coding features / bug fixes, other ways to assist include spec writing, design, documentation, and finding bugs. We are excited to work with the power user community to build a set of tools for helping you get the most out of Windows. We ask that before you start work on a feature that you would like to contribute, please read our Contributor's Guide. We would be happy to work with you to figure out the best approach, provide guidance and mentorship throughout feature development, and help avoid any wasted or duplicate effort. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you grant us the rights to use your contribution and that you have permission to do so. For guidance on developing for PowerToys, please read the developer docs for a detailed breakdown. This includes how to setup your computer to compile.
Code of conduct
This project has adopted the Microsoft Open Source Code of Conduct.
Privacy statement
The application logs basic diagnostic data (telemetry). For more privacy information and what we collect, see our PowerToys Data and Privacy documentation.
