Boliang ZhangandCopilot 06e6ae43e2 feat(workspaces): add list and launch CLI (#51114)
<!-- 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>

![Workspaces CLI
list](https://github.com/user-attachments/assets/3755c810-0b85-4afe-b80f-f17f12e7f07d)
![Shared confirmation UI; controlled probe, no target
executed](https://github.com/user-attachments/assets/fbd09160-725d-47b7-907e-307bb2d749dc)

</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
2026-10-27 11:29:49 +08:00
2026-02-11 22:59:53 +01:00
2026-09-16 09:13:00 -07:00
2020-03-05 10:11:27 -08:00
2020-05-02 15:59:18 -07:00
2026-02-14 15:47:56 +08:00

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:

Advanced Paste icon Advanced Paste Always on Top icon Always on Top Awake icon Awake
Color Picker icon Color Picker Command Not Found icon Command Not Found Command Palette icon Command Palette
Crop and Lock icon Crop And Lock Environment Variables icon Environment Variables FancyZones icon FancyZones
File Explorer Add-ons icon File Explorer Add-ons File Locksmith icon File Locksmith Grab And Move icon Grab And Move
Hosts File Editor icon Hosts File Editor Image Resizer icon Image Resizer Keyboard Manager icon Keyboard Manager
Light Switch icon Light Switch Mouse Utilities icon Mouse Utilities Mouse Without Borders icon Mouse Without Borders
New+ icon New+ Peek icon Peek PowerDisplay icon PowerDisplay
PowerRename icon PowerRename PowerToys Run icon PowerToys Run Quick Accent icon Quick Accent
Registry Preview icon Registry Preview Screen Ruler icon Screen Ruler Shortcut Guide icon Shortcut Guide
Text Extractor icon Text Extractor Window Hopper icon Window Hopper Workspaces icon Workspaces
ZoomIt icon ZoomIt

📦 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.

Microsoft Store
You can easily install PowerToys from the Microsoft Store:

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?

What's new image

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.

Languages
C 39.9%
C# 31.3%
C++ 13.6%
JavaScript 12.5%
PowerShell 2.3%
Other 0.3%