winget-cli icon indicating copy to clipboard operation
winget-cli copied to clipboard

Powershell Module Should Support Scope Parameter

Open jordanabakerafs opened this issue 1 year ago • 5 comments

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"

jordanabakerafs avatar Sep 04 '24 12:09 jordanabakerafs

[Policy] PowerShell

mdanish-kh avatar Sep 04 '24 14:09 mdanish-kh

Seems like it's included See https://github.com/microsoft/winget-cli/issues/4798#issuecomment-2438598369

Karl-WE avatar Nov 17 '24 09:11 Karl-WE

Looking at the current code, Scope is inconsistently applied across commands. e.g. Install-WinGetPackage implements Scope but Uninstall-WinGetPackage does not.

jgause-bema avatar Feb 26 '25 17:02 jgause-bema

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

  1. Add -Scope to Get, Repair, and Uninstall
  2. Allow scope to be passed down to the composite catalog options
  3. Ensure that scope is passed down for Get, Repair, 'Install, 'Update, and Uninstall

JohnMcPMS avatar Mar 27 '25 18:03 JohnMcPMS

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.

CSVDK avatar May 08 '25 12:05 CSVDK

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.

o-l-a-v avatar Sep 11 '25 09:09 o-l-a-v

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.

CSVDK avatar Sep 22 '25 06:09 CSVDK

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 avatar Sep 22 '25 07:09 CSVDK

@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:

o-l-a-v avatar Sep 22 '25 08:09 o-l-a-v