Bring Pinning to PowerShell Cmdlets#6190
Conversation
|
Were you able to figure out the PlatyPS MAML stuff for the PowerShell help? |
|
There was a problem hiding this comment.
Pull request overview
This PR expands WinGet’s pinning feature end-to-end (repository schema + CLI workflow + COM/WinRT API + PowerShell cmdlets), adding pin metadata (DateAdded, Note), a new winget pin show command, and PowerShell cmdlets to manage pins.
Changes:
- Add
DateAddedandNotesupport to the pinning index (schema v1.1) with migration from v1.0. - Extend the COM API surface for pin management (get/pin/unpin/reset) and expose
PackagePin,PinPackageOptions,PinPackageResult. - Add PowerShell cmdlets (
Get/Add/Remove/Reset-WinGetPin) and related PS output objects/help.
Reviewed changes
Copilot reviewed 59 out of 59 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| src/PowerShell/Microsoft.WinGet.Client/ModuleFiles/Microsoft.WinGet.Client.psd1 | Exports new pin cmdlets from the module. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/PSObjects/PSPinResult.cs | Adds PS wrapper for COM pin operation results. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/PSObjects/PSPackagePin.cs | Adds PS wrapper for COM PackagePin objects. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/PSObjects/PSInstalledCatalogPackage.cs | Adds IsPinned property on installed package output objects. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/PackageManagerWrapper.cs | Adds wrapper methods for new COM pin APIs. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/PSEnumHelpers.cs | Adds conversion helper for PackagePinType. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/ManagementDeploymentFactory.cs | Adds COM factory creation for PinPackageOptions. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/ResetPinCommand.cs | Adds engine command to reset pins via COM. |
| src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/PinPackageCommand.cs | Adds engine command to get/add/remove pins via COM. |
| src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Common/Constants.cs | Adds parameter sets and noun constant for pin cmdlets. |
| src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Cmdlets/ResetPinCmdlet.cs | Adds Reset-WinGetPin cmdlet. |
| src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Cmdlets/RemovePinCmdlet.cs | Adds Remove-WinGetPin cmdlet (supports pipeline pin input). |
| src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Cmdlets/PSObjects/PSPackagePinType.cs | Adds PowerShell-facing enum for pin types. |
| src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Cmdlets/GetPinCmdlet.cs | Adds Get-WinGetPin cmdlet. |
| src/PowerShell/Microsoft.WinGet.Client.Cmdlets/Cmdlets/AddPinCmdlet.cs | Adds Add-WinGetPin cmdlet (type/gatedVersion/note/force). |
| src/PowerShell/Help/Microsoft.WinGet.Client/Reset-WinGetPin.md | Adds help documentation for reset pin cmdlet. |
| src/PowerShell/Help/Microsoft.WinGet.Client/Remove-WinGetPin.md | Adds help documentation for remove pin cmdlet. |
| src/PowerShell/Help/Microsoft.WinGet.Client/Microsoft.WinGet.Client.md | Adds module index entries for new cmdlets. |
| src/PowerShell/Help/Microsoft.WinGet.Client/Get-WinGetPin.md | Adds help documentation for get pin cmdlet. |
| src/PowerShell/Help/Microsoft.WinGet.Client/Add-WinGetPin.md | Adds help documentation for add pin cmdlet. |
| src/Microsoft.Management.Deployment/Public/ComClsids.h | Adds CLSIDs for PinPackageOptions activation. |
| src/Microsoft.Management.Deployment/PinPackageResult.h | Introduces WinRT result type for pin operations. |
| src/Microsoft.Management.Deployment/PinPackageResult.cpp | Implements WinRT result type for pin operations. |
| src/Microsoft.Management.Deployment/PinPackageOptions.h | Introduces WinRT options type for pin operations. |
| src/Microsoft.Management.Deployment/PinPackageOptions.cpp | Implements WinRT options type for pin operations. |
| src/Microsoft.Management.Deployment/PackagePin.h | Introduces WinRT PackagePin runtimeclass. |
| src/Microsoft.Management.Deployment/PackagePin.cpp | Implements WinRT PackagePin object creation from internal pins. |
| src/Microsoft.Management.Deployment/PackageManager.idl | Adds pinning APIs + types to the public WinRT contract. |
| src/Microsoft.Management.Deployment/PackageManager.h | Declares new PackageManager pinning methods. |
| src/Microsoft.Management.Deployment/PackageManager.cpp | Implements GetPins/GetAllPins/Pin/Unpin/Reset via pinning data store. |
| src/Microsoft.Management.Deployment/Microsoft.Management.Deployment.vcxproj | Adds new pin-related source/header files to project build. |
| src/Microsoft.Management.Deployment/Converters.h | Declares GetPinOperationStatus mapping. |
| src/Microsoft.Management.Deployment/Converters.cpp | Implements HRESULT→PinResultStatus mapping. |
| src/Microsoft.Management.Deployment/ComClsids.cpp | Enables in-proc→out-of-proc redirection for PinPackageOptions. |
| src/Microsoft.Management.Deployment.Projection/WinGetProjectionFactory.cs | Adds projection factory method for PinPackageOptions. |
| src/Microsoft.Management.Deployment.Projection/ClassesDefinition.cs | Registers PinPackageOptions class for projection activation. |
| src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_1/PinningIndexInterface_1_1.cpp | Adds v1.1 pinning schema interface + migration path. |
| src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_1/PinningIndexInterface.h | Declares v1.1 schema interface. |
| src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_1/PinTable.h | Declares v1.1 pin table with new columns. |
| src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_1/PinTable.cpp | Implements v1.1 pin table CRUD/migration including note/date. |
| src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_0/PinningIndexInterface_1_0.cpp | Implements MigrateFrom for v1.0 (not supported). |
| src/AppInstallerRepositoryCore/Microsoft/Schema/Pinning_1_0/PinningIndexInterface.h | Adds MigrateFrom to v1.0 interface declaration. |
| src/AppInstallerRepositoryCore/Microsoft/Schema/IPinningIndex.h | Adds MigrateFrom to schema interface abstraction. |
| src/AppInstallerRepositoryCore/Microsoft/PinningIndex.h | Adds helper to create schema interface for a specific version. |
| src/AppInstallerRepositoryCore/Microsoft/PinningIndex.cpp | Implements migration-on-open for pinning index and version dispatch. |
| src/AppInstallerRepositoryCore/AppInstallerRepositoryCore.vcxproj | Adds v1.1 pinning schema files to repository core build. |
| src/AppInstallerCommonCore/Public/winget/Pin.h | Adds DateAdded + Note fields to internal Pin model. |
| src/AppInstallerCLITests/PinningIndex.cpp | Adds unit tests for v1.1 schema and migration behavior. |
| src/AppInstallerCLITests/PinFlow.cpp | Adds workflow tests for note/date and new pin show behavior. |
| src/AppInstallerCLIPackage/Shared/Strings/en-us/winget.resw | Adds localized strings for --note and pin show output. |
| src/AppInstallerCLIPackage/Package.appxmanifest | Registers COM server class for PinPackageOptions (dev out-of-proc). |
| src/AppInstallerCLICore/Workflows/PinFlow.h | Declares new workflow step ShowPinDetails. |
| src/AppInstallerCLICore/Workflows/PinFlow.cpp | Sets date/note on add; implements winget pin show output filtering. |
| src/AppInstallerCLICore/Resources.h | Adds resource IDs for new pin strings. |
| src/AppInstallerCLICore/ExecutionArgs.h | Adds PinNote execution arg. |
| src/AppInstallerCLICore/Commands/PinCommand.h | Adds PinShowCommand declaration. |
| src/AppInstallerCLICore/Commands/PinCommand.cpp | Wires up winget pin show and adds --note to pin add. |
| src/AppInstallerCLICore/Argument.cpp | Adds CLI argument mapping for --note. |
| .github/actions/spelling/expect.txt | Adds expected spelling words introduced by new tests/log strings. |
| std::make_unique<PinRemoveCommand>(FullName()), | ||
| std::make_unique<PinListCommand>(FullName()), | ||
| std::make_unique<PinResetCommand>(FullName()), | ||
| std::make_unique<PinShowCommand>(FullName()), |
There was a problem hiding this comment.
I would prefer that we follow the model of package list and have --details on the existing list command. That also removes the need to create a whole new search mechanism and just makes the change in ReportPins.
Followup: Well it looks like it would need a whole new search mechanism to actually implement the arguments that it claims to support...
There was a problem hiding this comment.
Yes, we would need a whole new search mechanism anyways. I do think that there is some overlap with winget list <query> --details, but to me it felt more akin to winget show <query>. The semantics of list vs show as a base command don't really apply to pins. Where show in the base command is for a remote package / manifest information, list is for installed applications.
I will think on this and probably end up refactoring to extend the behavior of list instead of adding show
| auto newPin = CreatePinFromOptions(pinKey, options); | ||
|
|
||
| auto existingPin = pinningData.GetPin(pinKey); | ||
| if (existingPin && !(*existingPin == newPin)) |
There was a problem hiding this comment.
Shouldn't this only be comparing the pin type rather than the entire pin?
There was a problem hiding this comment.
I don't think so. The CLI compares the version as well for gating pins so that updating a gating pin by overwriting it requires --force . e.g winget pin add Microsoft.WingetCreate --version 1.9 and then running winget pin add Microsoft.WingetCreate --version 1.10 would give an error that there is already a pin and it needs to be overriden.
This matches the behavior of the CLI
| /// <summary> | ||
| /// Must match the user-settable values of Microsoft.Management.Deployment.PackagePinType. | ||
| /// </summary> | ||
| public enum PSPackagePinType |
There was a problem hiding this comment.
Do we need the "pinned by the manifest" type?
There was a problem hiding this comment.
I don't believe we do, since it isn't user-settable and the CLI doesn't expose it when listing pins as far as I can tell
It is no longer needed since the interface surface is so small
This comment has been minimized.
This comment has been minimized.
* Updated .github/copilot-instructions.md
| bool hasName = context.Args.Contains(Execution::Args::Type::Name); | ||
| bool hasQuery = context.Args.Contains(Execution::Args::Type::Query); | ||
| bool exactMatch = context.Args.Contains(Execution::Args::Type::Exact); | ||
|
|
There was a problem hiding this comment.
winget pin show currently allows running with no query/id/name arguments, in which case it will match every pin and dump verbose details for all of them. This seems inconsistent with the intent of a "show" command (and the comment above suggests at least one filter is expected). Consider enforcing that at least one of --id/--name/--query is provided and terminating with an appropriate error message when none are specified.
| if (!hasId && !hasName && !hasQuery) | |
| { | |
| context.Reporter.Error() << "The 'pin show' command requires at least one of --id, --name, or --query." << std::endl; | |
| AICLI_TERMINATE_CONTEXT(APPINSTALLER_CLI_ERROR_INVALID_CL_ARGUMENTS); | |
| } |
Summary
This PR extends the WinGet pinning system with new metadata, a new CLI subcommand, expanded COM API surface, and PowerShell cmdlets for managing pins.
CLI Changes
winget pin add: Added--noteargument to attach an optional freeform note to a pin. The timestamp when a pin is created is now recorded automatically.winget pin show: New subcommand that displays detailed information about pins for a specific package (query by ID, name, or keyword).Pinning Index Schema (v1.1)
DateAddedandNotecolumns to the pin table to persist the new metadata.COM API (
Microsoft.Management.Deployment, contract v29)PackageManager.GetAllPins()— retrieve all pins across all sources.PackageManager.GetPins(CatalogPackage)— retrieve pins for a specific package.PackageManager.PinPackage(CatalogPackage, PinPackageOptions)— add or update a pin.PackageManager.UnpinPackage(CatalogPackage)— remove all pins for a package.PackageManager.ResetAllPins(String sourceName)— reset all pins, optionally scoped to a source.PackagePinruntime class exposingPackageId,SourceId,Type,GatedVersion,DateAdded,Note, andIsForInstalledPackage.PinPackageOptionsandPinPackageResultruntime classes.PackagePinTypeenum (PinnedByManifest,Pinning,Gating,Blocking).PowerShell (
Microsoft.WinGet.Client)Add-WinGetPin— pin a package with a specified pin type, optional gated version, note, and force flag.Get-WinGetPin— list pins, filterable by package/source.Remove-WinGetPin— remove pins for a package.Reset-WinGetPin— reset all pins, optionally scoped to a source.Get-WinGetPackage— newIsPinnedproperty on returned objects.cc @denelon for Naming
Microsoft Reviewers: Open in CodeFlow