-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Specification: PowerShell Module Full Parity #6290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
denelon
wants to merge
5
commits into
microsoft:master
Choose a base branch
from
denelon:spec/powershell-module-parity
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+309
β0
Draft
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
9b2bcb0
Add spec: PowerShell Module Full Parity (#6288)
334bd64
Clarify two-module architecture in PS parity spec
7246821
Address review feedback from Trenly
0697820
Address review feedback: correct overstated parity gaps
2a91419
Add SCCM and runbooks to spelling allow list
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,307 @@ | ||
| --- | ||
| author: Demitrius Nelon denelon, GitHub Copilot Copilot | ||
| created on: 2026-06-17 | ||
| last updated: 2026-06-23 | ||
| issue id: 6288 | ||
| --- | ||
|
|
||
| # PowerShell Module Full Parity with WinGet CLI | ||
|
|
||
| For [#6288](https://github.com/microsoft/winget-cli/issues/6288). | ||
|
|
||
| ## Abstract | ||
|
|
||
| WinGet ships two PowerShell modules β `Microsoft.WinGet.Client` (package management) and | ||
| `Microsoft.WinGet.Configuration` (configuration operations). The modules already cover the large | ||
| majority of the CLI surface. This spec establishes an accurate baseline of what exists today and | ||
| scopes the remaining work required to reach full parity. | ||
|
|
||
| After auditing the shipping source (`src/PowerShell/`) and the published modules, the true parity | ||
| work falls into three categories: | ||
|
|
||
| 1. **Genuine command gaps** β capabilities with no cmdlet equivalent today: **pin management** and | ||
| **package list import/export**. | ||
| 2. **Reliability bugs** β the module already supports elevated and SYSTEM contexts through dedicated | ||
| activation paths; where these fail it is a defect to fix, not a missing feature | ||
| ([#5991](https://github.com/microsoft/winget-cli/issues/5991), | ||
| [#6042](https://github.com/microsoft/winget-cli/issues/6042)). | ||
| 3. **Enhancement backlog** β smaller, issue-tracked improvements to existing cmdlets (richer detail | ||
| output, update-all, multiple IDs, cancellation, `-WhatIf`/`-Debug`). | ||
|
|
||
| ## Inspiration | ||
|
|
||
| IT decision makers evaluating WinGet for large-scale deployment cite incomplete PowerShell support | ||
| as a blocker. Enterprise automation operates in PowerShell-only contexts (Intune, SCCM, Azure | ||
| Automation, DSC) where shelling out to `winget.exe` and parsing text is unreliable. Closing the | ||
| remaining gaps and hardening elevated/SYSTEM execution lets these workflows stay native. | ||
|
|
||
| ## Current State β What Already Exists | ||
|
|
||
| This inventory is the corrected baseline. Earlier drafts of this spec proposed cmdlets that already | ||
| ship; those are recorded here as **existing** so the parity gap is not overstated. | ||
|
|
||
| ### Microsoft.WinGet.Client (package management) | ||
|
|
||
| | CLI command | Existing cmdlet | Notes | | ||
| |-------------|-----------------|-------| | ||
| | `winget install` | `Install-WinGetPackage` | Supports `-Scope` ([#4787](https://github.com/microsoft/winget-cli/issues/4787)) | | ||
| | `winget upgrade` | `Update-WinGetPackage` | Supports `-Scope` | | ||
| | `winget uninstall` | `Uninstall-WinGetPackage` | | | ||
| | `winget search` | `Find-WinGetPackage` | | | ||
| | `winget list` | `Get-WinGetPackage` | | | ||
| | `winget download` | `Export-WinGetPackage` | Downloads a package and its dependencies; `-Scope` supported | | ||
| | `winget repair` | `Repair-WinGetPackage` | | | ||
| | `winget source add/remove/reset/list` | `Add/Remove/Reset/Get-WinGetSource` | | | ||
| | `winget settings` (user file) | `Get/Set/Test-WinGetUserSetting` | Read, write, and validate the user settings JSON | | ||
| | `winget settings` (admin) | `Get-WinGetSetting`, `Enable/Disable-WinGetSetting` | Admin/toggle settings | | ||
| | `winget --version` | `Get-WinGetVersion` | | | ||
| | (bootstrap) | `Assert/Repair-WinGetPackageManager` | Verify/repair the WinGet installation itself | | ||
|
|
||
| ### Microsoft.WinGet.Configuration (configuration operations) | ||
|
|
||
| | CLI command | Existing cmdlet | Notes | | ||
| |-------------|-----------------|-------| | ||
| | `winget configure` / `apply` | `Invoke-WinGetConfiguration`, `Start/Complete-WinGetConfiguration` | Synchronous and async apply | | ||
| | `winget configure test` | `Test-WinGetConfiguration` | Tests system state against the set | | ||
| | `winget configure show` | `Get-WinGetConfigurationDetails` | | | ||
| | `winget configure list` | `Get-WinGetConfiguration` | History via `-...FromHistory` parameter sets | | ||
| | `winget configure abort` | `Stop-WinGetConfiguration` | | | ||
| | `winget configure delete` | `Remove-WinGetConfigurationHistory` | | | ||
| | (open/confirm/convert) | `Get/Confirm-WinGetConfiguration`, `ConvertTo-WinGetConfigurationYaml` | | | ||
|
|
||
| > Note: `Microsoft.WinGet.Configuration` communicates with the **`Microsoft.Management.Configuration`** | ||
| > WinRT API (and its processor), **not** `Microsoft.Management.Deployment`. The two modules do not | ||
| > share a COM surface. | ||
|
|
||
| ## Solution Design | ||
|
|
||
| ### Gap 1 β Pin Management (Microsoft.WinGet.Client) | ||
|
|
||
| There is no PowerShell equivalent for `winget pin add/remove/list/reset` today. This is the largest | ||
| genuine parity gap. | ||
|
|
||
| | CLI command | Proposed cmdlet | Verb justification | | ||
| |-------------|-----------------|--------------------| | ||
| | `winget pin add` | `Add-WinGetPin` | `Add` = create resource | | ||
| | `winget pin list` | `Get-WinGetPin` | `Get` = list/retrieve | | ||
| | `winget pin remove` | `Remove-WinGetPin` | `Remove` = delete resource | | ||
| | `winget pin reset` | `Reset-WinGetPin` | `Reset` = restore defaults | | ||
|
|
||
| Pins are modeled with a **`PinType`** rather than a boolean, so the output can describe pinning, | ||
| blocking, and gating pins as the feature evolves (per review feedback): | ||
|
|
||
| ```powershell | ||
| # Pinning pin (excluded from `upgrade --all`, still upgradeable explicitly) | ||
| Add-WinGetPin -Id "Microsoft.VisualStudioCode" | ||
|
|
||
| # Blocking pin (no upgrades at all) | ||
| Add-WinGetPin -Id "Microsoft.VisualStudioCode" -Blocking | ||
|
|
||
| # Gating pin (pin to a version range, e.g. 1.2.*) | ||
| Add-WinGetPin -Id "Microsoft.VisualStudioCode" -Version "1.2.*" | ||
|
|
||
| Get-WinGetPin [-Id <String>] # returns objects with Id, Version, Source, PinType | ||
| Remove-WinGetPin -Id "Microsoft.VisualStudioCode" | ||
| Reset-WinGetPin [-Force] | ||
| ``` | ||
|
|
||
| `Get-WinGetPin` output object: | ||
|
|
||
| | Property | Description | | ||
| |----------|-------------| | ||
| | `Id` | Package identifier | | ||
| | `Source` | Source the pin applies to | | ||
| | `Version` | Pinned version or range (gating pins) | | ||
| | `PinType` | `Pinning`, `Blocking`, or `Gating` | | ||
|
|
||
| Automation can branch on `PinType` directly: | ||
|
|
||
| ```powershell | ||
| if (Get-WinGetPin -Id "Microsoft.Edge" | Where-Object PinType -eq 'Blocking') { | ||
| Write-Output "Edge is blocked from upgrade - compliant" | ||
| } | ||
| ``` | ||
|
|
||
| ### Gap 2 β Package List Import / Export (Microsoft.WinGet.Client) | ||
|
|
||
| `winget export` (serialize installed packages to a JSON list) and `winget import` (install from such | ||
| a list) have no cmdlet equivalent ([#5041](https://github.com/microsoft/winget-cli/issues/5041)). | ||
| This is distinct from `Export-WinGetPackage`, which downloads installers. | ||
|
|
||
| To avoid colliding with the existing `Export-WinGetPackage` (download) noun, the list operations use | ||
| a dedicated noun: | ||
|
|
||
| ```powershell | ||
| # Serialize installed packages to a WinGet import/export JSON file | ||
| Export-WinGetPackageList -OutputFile "C:\state\packages.json" | ||
| [-Source <String>] [-IncludeVersions] | ||
|
|
||
| # Install everything described by an export file | ||
| Import-WinGetPackageList -File "C:\state\packages.json" | ||
| [-IgnoreUnavailable] [-IgnoreVersions] [-AcceptPackageAgreements] [-AcceptSourceAgreements] | ||
| ``` | ||
|
|
||
| `Import-WinGetPackageList` returns one result object per package describing install status, so callers | ||
| can detect partial failures in automation. | ||
|
|
||
| > Naming is provisional. If the team prefers, these can ship as parameters on existing cmdlets; | ||
| > the requirement is that the installed-list import/export workflow becomes available without | ||
| > shelling out to `winget.exe`. | ||
|
|
||
| ### Reliability β Elevated and SYSTEM Context | ||
|
|
||
| The module already activates the COM API through a custom path for elevated callers and an in-proc | ||
| path for SYSTEM; this is not a missing feature. The parity work here is to **fix the defects** so | ||
| these paths are dependable for Intune/SCCM: | ||
|
|
||
| - SYSTEM context regression where `Get-WinGetPackage` exits immediately | ||
| ([#5991](https://github.com/microsoft/winget-cli/issues/5991), | ||
| [#4820](https://github.com/microsoft/winget-cli/issues/4820)). | ||
| - Elevated activation failing to see the packaged COM registration | ||
| ([#6042](https://github.com/microsoft/winget-cli/issues/6042), | ||
| [#5369](https://github.com/microsoft/winget-cli/issues/5369), | ||
| [#5635](https://github.com/microsoft/winget-cli/issues/5635)). | ||
|
|
||
| Note that successful *package operation* in a session-less context also depends on installer | ||
| behavior, which WinGet does not own; per-installer results cannot be guaranteed. | ||
|
|
||
| ### Enhancement Backlog (existing cmdlets) | ||
|
|
||
| These are issue-tracked refinements, not new commands. They are listed for completeness and can be | ||
| scheduled independently of the gaps above: | ||
|
|
||
| - Richer package detail output / `list --details` | ||
| ([#6055](https://github.com/microsoft/winget-cli/issues/6055), | ||
| [#6144](https://github.com/microsoft/winget-cli/issues/6144), | ||
| [#5129](https://github.com/microsoft/winget-cli/issues/5129)) | ||
| - Update-all for `Update-WinGetPackage` ([#5495](https://github.com/microsoft/winget-cli/issues/5495)) | ||
| - Multiple package IDs in a single call ([#5094](https://github.com/microsoft/winget-cli/issues/5094)) | ||
| - `Ctrl+C` cancellation of download/install ([#4961](https://github.com/microsoft/winget-cli/issues/4961)) | ||
| - `-WhatIf` honored by `Update-WinGetPackage` ([#4622](https://github.com/microsoft/winget-cli/issues/4622)) | ||
| - `-Debug` support ([#4697](https://github.com/microsoft/winget-cli/issues/4697)) | ||
|
|
||
| ### Architecture | ||
|
|
||
| Both modules use the existing WinRT COM APIs rather than wrapping `winget.exe`. They target | ||
| **different** APIs: | ||
|
|
||
| ``` | ||
| ββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββ | ||
| β Microsoft.WinGet.Client β β Microsoft.WinGet.Configuration β | ||
| β (package management cmdlets) β β (configuration cmdlets) β | ||
| ββββββββββββββββ¬ββββββββββββββββββββ ββββββββββββββββ¬ββββββββββββββββββββ | ||
| β β | ||
| βΌ βΌ | ||
| ββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββ | ||
| β Microsoft.Management.Deployment β β Microsoft.Management.Configurationβ | ||
| β (package manager WinRT COM API) β β (configuration WinRT COM API) β | ||
| ββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββ | ||
| ``` | ||
|
|
||
| Using the COM APIs gives error propagation as PowerShell `ErrorRecord`s (with `HRESULT`), structured | ||
| output objects, `StopProcessing()` cancellation, `WriteProgress`, and pipeline support. | ||
|
|
||
| > Detailed COM interface design (IIDs, async signatures) is intentionally out of scope for this spec. | ||
| > Pin management requires a small addition to the `Microsoft.Management.Deployment` surface; the | ||
| > concrete interface shape is an implementation decision made during development. This spec defines | ||
| > the cmdlet inputs and outputs only. | ||
|
|
||
| ### Settings Changes | ||
|
|
||
| No new settings required. Existing settings apply identically to CLI and module operations. | ||
|
|
||
| ### Validation Pipeline Impact | ||
|
|
||
| No impact on `winget-pkgs` validation. Validation already uses the COM API for non-interactive | ||
| operation. | ||
|
|
||
| ## UI/UX Design | ||
|
|
||
| ### Pin management | ||
|
|
||
| ```powershell | ||
| PS> Add-WinGetPin -Id "Git.Git" -Version "2.45.*" | ||
| PS> Get-WinGetPin | ||
|
|
||
| Id Version Source PinType | ||
| -- ------- ------ ------- | ||
| Git.Git 2.45.* winget Gating | ||
| ``` | ||
|
|
||
| ### Import / export workflow | ||
|
|
||
| ```powershell | ||
| # Capture a machine's installed packages, then reproduce it elsewhere | ||
| Export-WinGetPackageList -OutputFile "\\share\golden.json" -IncludeVersions | ||
| Import-WinGetPackageList -File "\\share\golden.json" -IgnoreUnavailable | ||
| ``` | ||
|
|
||
| ### -Force behavior | ||
|
|
||
| New cmdlets support `-Force` to suppress confirmation prompts, consistent with existing cmdlets. | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### Accessibility | ||
|
|
||
| No direct impact β modules inherit the accessibility of the PowerShell host; all output is text-based | ||
| and screen-reader compatible. | ||
|
|
||
| ### Security | ||
|
|
||
| - Elevated/SYSTEM hardening must not bypass UAC for operations that require elevation in user context. | ||
| - Pin and import/export operations respect Group Policy; policy-managed state yields a terminating | ||
| error when a caller attempts to modify it. | ||
| - Credential/token parameters on source cmdlets remain `SecureString` where applicable. | ||
|
|
||
| ### Reliability | ||
|
|
||
| - Eliminates `Start-Process winget.exe` text parsing for the newly covered commands. | ||
| - COM `HRESULT`s map to PowerShell `ErrorRecord`s. | ||
| - `StopProcessing()` cancellation prevents orphaned installer processes. | ||
|
|
||
| ### Compatibility | ||
|
|
||
| - No breaking changes to existing cmdlets; new cmdlets follow established naming patterns. | ||
| - Minimum PowerShell version remains 7.2+; Windows PowerShell 5.1 is not supported, consistent with | ||
| the current modules. | ||
|
|
||
| ### Performance, Power, and Efficiency | ||
|
|
||
| - COM calls avoid per-operation `winget.exe` startup. | ||
| - Pipelining enables batch operations without repeated activation. | ||
|
|
||
| ## Potential Issues | ||
|
|
||
| 1. **Elevated/SYSTEM defects are environmental** β reproducing and fixing | ||
| [#5991](https://github.com/microsoft/winget-cli/issues/5991)/[#6042](https://github.com/microsoft/winget-cli/issues/6042) | ||
| requires testing across Intune/SCCM/session-less hosts; installer behavior in those contexts is | ||
| outside WinGet's control. | ||
| 2. **Pin COM surface** β pin management needs an additive `Microsoft.Management.Deployment` interface | ||
| (new IIDs) to avoid breaking existing COM consumers. | ||
| 3. **Import/export noun choice** β `Export-WinGetPackage` already means *download*. The list | ||
| operations must use a distinct noun (or parameters) to avoid ambiguity. | ||
| 4. **Backwards compatibility** β new cmdlets must not destabilize existing functionality via assembly | ||
| loading changes. | ||
|
|
||
| ## Future Considerations | ||
|
|
||
| - Full parity enables DSC resources to delegate directly to PowerShell cmdlets. | ||
| - Richer Intune remediation and proactive remediation scripts. | ||
| - Azure Automation runbooks managing packages across fleets. | ||
| - Potential `WinGet:` PowerShell drive provider (e.g. `Get-ChildItem WinGet:\installed\`). | ||
|
|
||
| ## Resources | ||
|
|
||
| - Client module: https://www.powershellgallery.com/packages/Microsoft.WinGet.Client | ||
| - Configuration module: https://www.powershellgallery.com/packages/Microsoft.WinGet.Configuration | ||
| - Package manager COM API source: `src/Microsoft.Management.Deployment/` | ||
| - Configuration COM API source: `src/Microsoft.Management.Configuration/` | ||
| - Client module source: `src/PowerShell/Microsoft.WinGet.Client/` | ||
| - Configuration module source: `src/PowerShell/Microsoft.WinGet.Configuration/` | ||
| - Pin management: [#6288](https://github.com/microsoft/winget-cli/issues/6288) | ||
| - Import/Export package list: [#5041](https://github.com/microsoft/winget-cli/issues/5041) | ||
| - SYSTEM context: [#5991](https://github.com/microsoft/winget-cli/issues/5991) | ||
| - Elevated COM: [#6042](https://github.com/microsoft/winget-cli/issues/6042) | ||
| - Scope parameter (already shipped): [#4787](https://github.com/microsoft/winget-cli/issues/4787) | ||
| - Configuration module improvements PR: [#6190](https://github.com/microsoft/winget-cli/pull/6190) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.