Powershell Module Should Support Scope Parameter
Description of the new feature / enhancement
Currently the winget-cli module supports a --scope parameter which can be set to user or machine.
https://learn.microsoft.com/en-us/windows/package-manager/winget/install#options
The current powershell implementation (Microsoft.Winget.Client) does not appear to support the scope parameter. Looking through the README doesn't speak to this one way or another, but looking at https://github.com/microsoft/winget-cli/blob/master/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/FinderPackageCommand.cs it appears the parameter is not currently supported.
Adding a scope parameter to the Powershell implementation would provide a powershell native way to manage machine level packages. This would be particularly useful when working with Intune, which currently only executes Powershell remotely and has no good way to execute winget as an administrator at the user scope.
Proposed technical implementation details
Implement a new scope parameter that supports the "Machine" and "User" values to bring parity with the current winget cli tool.
EX: Get-WinGetPackage -Scope "Machine"
[Policy] PowerShell
Seems like it's included See https://github.com/microsoft/winget-cli/issues/4798#issuecomment-2438598369
Looking at the current code, Scope is inconsistently applied across commands. e.g. Install-WinGetPackage implements Scope but Uninstall-WinGetPackage does not.
Description of the new feature / enhancement
The Get, Repair, and Uninstall -WinGetPackage cmdlets don't currently take in a -Scope parameter, but they should. Additionally, the Install and Upgrade -WinGetPackage cmdlets don't properly pipe the requested scope into the composite package catalog options.
Generally, the feature is to allow the user to specify the scope of the installed package view that will be used from PowerShell.
Proposed technical implementation details
- Add
-ScopetoGet,Repair, andUninstall - Allow scope to be passed down to the composite catalog options
- Ensure that scope is passed down for
Get,Repair, 'Install, 'Update, andUninstall
Any progress on this?
I really miss te scope parameter for uninstall-wingetpackage because when I have an installation that is installed for both the user and the system it can't be uninstalled using uninstall-wingetpackage. The error returned is: -1978335210 APPINSTALLER_CLI_ERROR_MULTIPLE_APPLICATIONS_FOUND Multiple packages found matching the criteria
The uninstall can only be performed with the CLI because that does support the scope parameter for uninstall.
Also the scope for get-wingetpackage would really be appreciated as to be able to determin in what scope(s) the app is currently installed.
Here's a little hack while we wait.
<#
Main issue:
* 2024-09-04 "Powershell Module Should Support Scope Parameter": <https://github.com/microsoft/winget-cli/issues/4787>
Related issues:
* 2020-15-19 "JSON Formatted Output Support": <https://github.com/microsoft/winget-cli/issues/184>
* 2023-03-13 "Increasing terminal width doesn't address truncation": <https://github.com/microsoft/winget-cli/issues/3071>
About character encoding:
* 2024-05-17: <https://github.com/microsoft/winget-cli/issues/4491>
* PowerShell: <https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding#character-encoding-in-powershell>
* Windows PowerShell: <https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_character_encoding#character-encoding-in-windows-powershell>
#>
# Set encoding to UTF8 to mitigate scrambled output from winget-cli
if ($PSVersionTable.'PSEdition' -eq 'Core') {
[console]::InputEncoding = [console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
}
else {
# Workaround for PowerShell ISE "Exception setting "OutputEncoding": "The handle is invalid.""
if ($Host.Name -eq 'Windows PowerShell ISE Host') {
$null = cmd /c ''
}
$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
}
# List apps with scope from winget-cli, as the PowerShell module does not support this
$CliListUserScope = [string](
winget list --scope user | Where-Object -FilterScript {
$_ -notmatch '^\s' -and
-not [string]::IsNullOrWhiteSpace($_) -and
$_.TrimEnd() -match 'winget$'
} | Out-String
)
# List apps with the PowerShell module so we don't have to parse the output of winget-cli manually + add scope by output from previous step
$ListApps = [PSCustomObject[]](
Microsoft.WinGet.Client\Get-WinGetPackage -Source 'Winget' | Where-Object -FilterScript {
$_.'Source' -eq 'winget'
} | Sort-Object -Property 'Name' | Select-Object -Property '*', @{
'Name' = 'Scope'
'Expression' = {
[string](
$(
if ([regex]::Match($CliListUserScope, ('(?i){0}' -f [regex]::Escape($_.'Id'))).'Success') {
'User'
}
else {
'Machine'
}
)
)
}
}
)
For me this gave output:
PS > $ListApps | Format-Table -AutoSize -Property 'Name', 'Id', 'InstalledVersion', 'Scope'
Name Id InstalledVersion Scope
---- -- ---------------- -----
7-Zip 7zip.7zip 25.01 Machine
App Installer Microsoft.AppInstaller 1.26.430.0 User
Discord Discord.Discord 1.0.9207 User
Jabra Direct Jabra.Direct 6.24.20901 Machine
Lenovo System Update Lenovo.SystemUpdate 5.08.03.59 Machine
Logi Options+ Logitech.OptionsPlus 1.94.762104 Machine
Microsoft .NET Windows Desktop Runtime 8.0 Microsoft.DotNet.DesktopRuntime.8 8.0.20 Machine
Microsoft 365 Apps for enterprise Microsoft.Office 16.0.19127.20192 Machine
Microsoft Edge Microsoft.Edge 140.0.3485.54 Machine
Microsoft OneDrive Microsoft.OneDrive 25.155.0811.0002 Machine
Microsoft Teams Microsoft.Teams 25227.203.3915.2444 User
Microsoft Visual C++ 2015 UWP Desktop Runtime Package Microsoft.VCLibs.Desktop.14 14.0.33728.0 User
Microsoft Visual C++ 2015-2022 Redistributable (x64) Microsoft.VCRedist.2015+.x64 14.44.35211.0 Machine
Microsoft Visual Studio Code Microsoft.VisualStudioCode 1.103.2 User
Microsoft.UI.Xaml Microsoft.UI.Xaml.2.7 7.2409.9001.0 User
Microsoft.UI.Xaml Microsoft.UI.Xaml.2.8 8.2501.31001.0 User
Mozilla Firefox (en-US) Mozilla.Firefox 142.0.1 Machine
Notepad++ Notepad++.Notepad++ 8.8.5 Machine
OpenHashTab namazso.OpenHashTab 3.1.1 Machine
PowerToys Microsoft.PowerToys 0.94.0 User
Signal OpenWhisperSystems.Signal 7.70.0 User
Windows Terminal Microsoft.WindowsTerminal 1.23.12371.0 User
PS >
Edit: Made it PowerShell 5.1 compatible.
Hi o-l-a-v, Thx for your input. It works for most apps but not all. Long id's in the CLI output are truncated to fit on one line in the CLI so for those apps your script will fail. Still waiting for the PS module to support -scope parameter for Get-WinGetPackage.
If you want to get all user installed apps the following works reliably, but it's very slow.
get-wingetpackage -Source 'winget' | Where-Object {$_.source -eq 'winget' -and (winget list --scope user --id $_.id) -and $LASTEXITCODE -eq 0 }
@CSVDK: Thanks, good to know. I haven't encountered that long package IDs yet.
I also played with making the output width of winget-cli wider, but did not have success.
Would be even better if winget-cli supported JSON as an output format: