-
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
3
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.
+288
β0
Draft
Changes from all commits
Commits
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,288 @@ | ||
| --- | ||
| author: Demitrius Nelon denelon, GitHub Copilot Copilot | ||
| created on: 2026-06-17 | ||
| last updated: 2026-06-17 | ||
| 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/DSC operations). Both must achieve full functional parity with the WinGet CLI. Several CLI capabilities have no PowerShell equivalent today, blocking adoption by enterprise automation workflows that operate exclusively in PowerShell contexts (Intune, SCCM, Azure Automation, DSC). | ||
|
|
||
| ## Inspiration | ||
|
|
||
| IT decision makers evaluating WinGet for large-scale deployment cite incomplete PowerShell support as a blocking issue. Enterprise automation tooling operates in PowerShell-only contexts where shelling out to `winget.exe` is unreliable β especially in SYSTEM context ([#5991](https://github.com/microsoft/winget-cli/issues/5991)) β or architecturally inappropriate. | ||
|
|
||
| Key gaps identified by enterprise customers: | ||
|
|
||
| - No PowerShell equivalent for `winget configure` operations (test, validate, show) β these belong in `Microsoft.WinGet.Configuration` | ||
| - Missing cmdlets for pin management (`winget pin add/remove/list/reset`) | ||
| - No cmdlet for `winget download` ([#658](https://github.com/microsoft/winget-cli/issues/658) added CLI support) | ||
| - Missing `winget repair` support in the module ([#148](https://github.com/microsoft/winget-cli/issues/148) added CLI support) | ||
| - No PowerShell equivalent for `winget settings` management | ||
| - Limited source management beyond basic add/remove | ||
| - COM API cannot activate in elevated/SYSTEM context ([#6042](https://github.com/microsoft/winget-cli/issues/6042)) | ||
| - `Microsoft.WinGet.Configuration` lacks cmdlets for configuration history, abort, and delete operations | ||
|
|
||
| ## Solution Design | ||
|
|
||
| ### Module Architecture | ||
|
|
||
| WinGet ships two separate PowerShell modules with distinct responsibilities: | ||
|
|
||
| | Module | Responsibility | Gallery Link | | ||
| |--------|---------------|--------------| | ||
| | `Microsoft.WinGet.Client` | Package lifecycle β install, upgrade, uninstall, search, source, pin, download, settings | [PSGallery](https://www.powershellgallery.com/packages/Microsoft.WinGet.Client) | | ||
| | `Microsoft.WinGet.Configuration` | Configuration operations β apply, test, validate, show, history | [PSGallery](https://www.powershellgallery.com/packages/Microsoft.WinGet.Configuration) | | ||
|
|
||
| Both modules communicate with the WinGet COM API (`Microsoft.Management.Deployment`) but surface different subsets of functionality. This spec covers parity gaps in **both** modules. | ||
|
|
||
| ### Phase 1: Core Cmdlet Gaps β Microsoft.WinGet.Client | ||
|
|
||
| Add the following cmdlets to `Microsoft.WinGet.Client`: | ||
|
|
||
| | CLI Command | Proposed Cmdlet | Verb-Noun Justification | | ||
| |-------------|----------------|------------------------| | ||
| | `winget download` | `Save-WinGetPackage` | `Save` = download without install (PS convention) | | ||
| | `winget repair` | `Repair-WinGetPackage` | `Repair` = fix broken install | | ||
| | `winget pin add` | `Add-WinGetPin` | `Add` = create resource | | ||
| | `winget pin remove` | `Remove-WinGetPin` | `Remove` = delete resource | | ||
| | `winget pin list` | `Get-WinGetPin` | `Get` = list/retrieve | | ||
| | `winget pin reset` | `Reset-WinGetPin` | `Reset` = restore defaults | | ||
| | `winget settings export` | `Export-WinGetSettings` | `Export` = serialize to file | | ||
| | `winget settings set` | `Set-WinGetSetting` | `Set` = modify value | | ||
|
|
||
| ### Phase 1b: Core Cmdlet Gaps β Microsoft.WinGet.Configuration | ||
|
|
||
| Add or enhance the following cmdlets in `Microsoft.WinGet.Configuration`: | ||
|
|
||
| | CLI Command | Proposed Cmdlet | Verb-Noun Justification | | ||
| |-------------|----------------|------------------------| | ||
| | `winget configure test` | `Test-WinGetConfiguration` | `Test` = validate state compliance | | ||
| | `winget configure validate` | `Assert-WinGetConfiguration` | `Assert` = validate schema/syntax | | ||
| | `winget configure show` | `Get-WinGetConfigurationDetails` | `Get` = retrieve information | | ||
| | `winget configure list` | `Get-WinGetConfigurationHistory` | `Get` = list previous runs | | ||
| | `winget configure abort` | `Stop-WinGetConfiguration` | `Stop` = cancel in-progress operation | | ||
| | `winget configure delete` | `Remove-WinGetConfigurationHistory` | `Remove` = delete record | | ||
|
|
||
| ### Phase 2: Enhanced Source Management | ||
|
|
||
| Extend `Get-WinGetSource`, `Add-WinGetSource`, `Remove-WinGetSource`: | ||
|
|
||
| - Full parameter parity (custom headers, certificates, authentication tokens) | ||
| - `Update-WinGetSource` for refresh operations (equivalent to `winget source update`) | ||
| - Source group policy awareness β report when sources are policy-managed with a `PolicyManaged` property | ||
|
|
||
| ### Phase 3: SYSTEM Context Support | ||
|
|
||
| Address the fundamental blocker of WinGet operating in SYSTEM context: | ||
|
|
||
| - The COM API (`Microsoft.Management.Deployment`) must properly initialize in SYSTEM context | ||
| - Package operations must work without a logged-in user session | ||
| - Source management must work in SYSTEM context for Intune and SCCM deployments | ||
| - Related to [#6042](https://github.com/microsoft/winget-cli/issues/6042) and [#5991](https://github.com/microsoft/winget-cli/issues/5991) | ||
|
|
||
| ### Architecture | ||
|
|
||
| Both modules use the existing COM API rather than wrapping the CLI executable: | ||
|
|
||
| ``` | ||
| ββββββββββββββββββββββββββββββββββββ ββββββββββββββββββββββββββββββββββββ | ||
| β Microsoft.WinGet.Client β β Microsoft.WinGet.Configuration β | ||
| β (Package management cmdlets) β β (Configuration/DSC cmdlets) β | ||
| ββββββββββββββββ¬ββββββββββββββββββββ ββββββββββββββββ¬ββββββββββββββββββββ | ||
| β COM Interop β COM Interop | ||
| βββββββββββββββββ¬ββββββββββββββββββββββ | ||
| βΌ | ||
| ββββββββββββββββββββββββββββββββββββ | ||
| β Microsoft.Management.Deployment β | ||
| β (WinRT COM API) β | ||
| ββββββββββββββββ¬ββββββββββββββββββββ | ||
| β | ||
| βΌ | ||
| ββββββββββββββββββββββββββββββββββββ | ||
| β WindowsPackageManagerServer β | ||
| β (WinGetDev.exe / winget.exe) β | ||
| ββββββββββββββββββββββββββββββββββββ | ||
| ``` | ||
|
|
||
| Benefits: | ||
| - Proper error propagation as PowerShell exceptions (`ErrorRecord` with `HRESULT`) | ||
| - Structured output objects (not parsed text) | ||
| - Cancellation support via `Ctrl+C` / `StopProcessing()` | ||
| - Progress reporting via `WriteProgress` | ||
| - Pipeline support for batch operations | ||
|
|
||
| ### COM API Surface Additions | ||
|
|
||
| New COM interfaces will be needed in `Microsoft.Management.Deployment` for pin management and settings. These should expose async operations consistent with the existing API patterns (e.g., `IAsyncOperationWithProgress` for pin add/remove/reset, string-based settings get/set/export). Detailed interface design will be determined during implementation. | ||
|
|
||
| ### PowerShell Cmdlet Details | ||
|
|
||
| #### Save-WinGetPackage | ||
|
|
||
| ```powershell | ||
| Save-WinGetPackage | ||
| [-Id] <String> | ||
| [-Version <String>] | ||
| [-Source <String>] | ||
| [-Architecture <Architecture>] | ||
| [-InstallerType <InstallerType>] | ||
| [-Scope <PackageScope>] | ||
| [-OutputDirectory <String>] # Required | ||
| [-AcceptSourceAgreements] | ||
| [-AcceptPackageAgreements] | ||
| [-Force] | ||
| ``` | ||
|
|
||
| Output: `WinGetDownloadResult` object with `InstallerPath`, `InstallerType`, `Sha256`, `Status`. | ||
|
|
||
| #### Test-WinGetConfiguration | ||
|
|
||
| ```powershell | ||
| Test-WinGetConfiguration | ||
| [-File] <String> | ||
| [-AcceptConfigurationAgreements] | ||
| ``` | ||
|
|
||
| Output: `WinGetConfigurationTestResult` object with per-resource compliance status: | ||
|
|
||
| ```powershell | ||
| $result = Test-WinGetConfiguration -File .\config.dsc.yaml | ||
| $result.UnitResults | Format-Table ResourceName, State, InDesiredState | ||
| ``` | ||
|
|
||
| #### Add-WinGetPin / Remove-WinGetPin / Get-WinGetPin | ||
|
|
||
| ```powershell | ||
| # Pin to prevent upgrades | ||
| Add-WinGetPin -Id "Microsoft.VisualStudioCode" [-Version <String>] [-Blocking] | ||
|
|
||
| # List pins | ||
| Get-WinGetPin [-Id <String>] | ||
|
|
||
| # Remove pin | ||
| Remove-WinGetPin -Id "Microsoft.VisualStudioCode" | ||
|
|
||
| # Reset all pins | ||
| Reset-WinGetPin [-Force] | ||
| ``` | ||
|
|
||
| ### Settings Changes | ||
|
|
||
| No new settings required. Existing settings continue to apply to both CLI and PowerShell module operations identically. | ||
|
|
||
| ### Validation Pipeline Impact | ||
|
|
||
| No impact on `winget-pkgs` validation. Validation already uses the COM API for non-interactive operation. | ||
|
|
||
| ## UI/UX Design | ||
|
|
||
| ### Interactive Mode | ||
|
|
||
| ```powershell | ||
| PS> Save-WinGetPackage -Id "Git.Git" -OutputDirectory "C:\Packages" | ||
|
|
||
| Id : Git.Git | ||
| Version : 2.45.1 | ||
| Path : C:\Packages\Git-2.45.1-64-bit.exe | ||
| Sha256 : abc123... | ||
| Status : Ok | ||
| ``` | ||
|
|
||
| ### Pipeline Support | ||
|
|
||
| ```powershell | ||
| # Download multiple packages | ||
| "Git.Git", "Python.Python.3.12" | ForEach-Object { | ||
| Save-WinGetPackage -Id $_ -OutputDirectory "C:\Packages" | ||
| } | ||
|
|
||
| # Test configuration and filter failures | ||
| $result = Test-WinGetConfiguration -File .\config.dsc.yaml | ||
| $result.UnitResults | Where-Object { -not $_.InDesiredState } | ||
| ``` | ||
|
|
||
| ### Non-Interactive / Automation | ||
|
|
||
| ```powershell | ||
| # Intune remediation script | ||
| $pins = Get-WinGetPin | ||
| if ($pins | Where-Object { $_.Id -eq "Microsoft.Edge" -and $_.PinType -eq "Blocking" }) { | ||
| Write-Output "Edge is pinned - compliant" | ||
| exit 0 | ||
| } else { | ||
| Add-WinGetPin -Id "Microsoft.Edge" -Blocking | ||
| exit 1 | ||
| } | ||
| ``` | ||
|
|
||
| ### -Force Parameter Behavior | ||
|
|
||
| All new cmdlets support `-Force` to suppress confirmation prompts, consistent with existing cmdlets. | ||
|
|
||
| ## Capabilities | ||
|
|
||
| ### Accessibility | ||
|
|
||
| No direct impact β PowerShell modules inherit the accessibility of the terminal/host application. All output is text-based and works with screen readers through the PowerShell host. | ||
|
|
||
| ### Security | ||
|
|
||
| - SYSTEM context support must not bypass UAC for operations that require elevation in user context | ||
| - COM API activation in SYSTEM context validates caller identity | ||
| - Settings cmdlets respect Group Policy overrides (throw terminating error when attempting to modify policy-managed settings) | ||
| - Token/credential parameters are `SecureString` where applicable | ||
|
|
||
| ### Reliability | ||
|
|
||
| - Eliminates the unreliable pattern of `Start-Process winget.exe` with text parsing | ||
| - COM API provides structured error codes via `HRESULT` mapped to PowerShell `ErrorRecord` | ||
| - Proper cancellation via `StopProcessing()` prevents orphaned installer processes | ||
| - Retry logic for transient COM activation failures | ||
|
|
||
| ### Compatibility | ||
|
|
||
| - No breaking changes to existing cmdlets | ||
| - New cmdlets follow established naming patterns in the module | ||
| - Minimum PowerShell version remains 7.2+ (consistent with current module) | ||
| - Windows PowerShell 5.1 is NOT supported (consistent with current module) | ||
|
|
||
| ### Performance, Power, and Efficiency | ||
|
|
||
| - COM API calls avoid process startup overhead (no `winget.exe` launch per operation) | ||
| - Pipelining enables batch operations without repeated COM activation | ||
| - `Save-WinGetPackage` supports parallel downloads when used with `ForEach-Object -Parallel` | ||
|
|
||
| ## Potential Issues | ||
|
|
||
| 1. **SYSTEM context COM activation** β The WinGet COM server (`WindowsPackageManagerServer`) may require architectural changes to support activation outside a user session. This is the highest-risk item. | ||
| 2. **Configuration cmdlets depend on DSC runtime** β `Test-WinGetConfiguration` requires the DSC v3 runtime to be available. If unavailable, the cmdlet should throw a clear error with installation guidance. | ||
| 3. **Backwards compatibility testing** β Enterprises may pin to older module versions. New cmdlets must not destabilize existing functionality via assembly loading changes. | ||
| 4. **COM interface versioning** β New interfaces must be additive to avoid breaking existing COM consumers. Use new interface IIDs. | ||
| 5. **Scope parameter interactions** β `Save-WinGetPackage` with `-Scope machine` in a non-elevated session should fail early with a clear error, not after download. | ||
|
|
||
| ## Future Considerations | ||
|
|
||
| - Full parity enables DSC resources to delegate directly to PowerShell cmdlets | ||
| - Opens the path for WinGet to be fully operable as a PowerShell-native tool without the CLI | ||
| - Enables richer Intune remediation scripts and proactive remediations | ||
| - Azure Automation runbooks can manage packages across fleets | ||
| - Potential for a `WinGet` PowerShell drive provider (`Get-ChildItem WinGet:\installed\`) | ||
| - **Module consolidation**: Evaluate whether `Microsoft.WinGet.Client` and `Microsoft.WinGet.Configuration` should eventually merge into a single `Microsoft.WinGet` module. Keeping them separate today reduces install footprint for users who only need package management, but the split adds complexity for users who need both. A unified module could be considered once the configuration surface stabilizes. | ||
|
|
||
| ## Resources | ||
|
|
||
| - Current Client module: https://www.powershellgallery.com/packages/Microsoft.WinGet.Client | ||
| - Current Configuration module: https://www.powershellgallery.com/packages/Microsoft.WinGet.Configuration | ||
| - COM API source: `src/Microsoft.Management.Deployment/` | ||
| - PowerShell Client module source: `src/PowerShell/Microsoft.WinGet.Client/` | ||
| - PowerShell Configuration module source: `src/PowerShell/Microsoft.WinGet.Configuration/` | ||
| - SYSTEM context issue: https://github.com/microsoft/winget-cli/issues/5991 | ||
| - Elevated COM issue: https://github.com/microsoft/winget-cli/issues/6042 | ||
| - Scope parameter issue: https://github.com/microsoft/winget-cli/issues/4787 | ||
| - Configuration module improvements PR: 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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.