ethanbergstrom / Cobalt

A PowerShell Crescendo wrapper for WinGet
MIT License
39 stars 7 forks source link

Install-WinGetPackage local package newer than repo package causes Cobalt error #4

Closed Kizan closed 2 years ago

Kizan commented 2 years ago

Ran into an odd situation using Install-WinGetPackage. I was trying to install Microsoft.OneDrive. The current Winget Repo has an older version than what is installed on my test box. This threw an error in Cobalt as shown below.

I have Microsoft.OneDrive v21.245.1128.0002 installed but the repo version is v21.230.1107.0004

I can hide the message by using -ErrorAction:SilentlyContinue but figured someone would want to know about the issue.

Cobalt\0.0.10\Cobalt.psm1:320 char:13

                        param ($output)
                        if ($output) {
                            if ($output -match 'failed') {
                                Write-Error ($output -join "`r`n")
                            } else {
                                $output | ForEach-Object {
                                    if ($_ -match '\[(?<id>[\S]+)\] Version (?<version>[\S]+)' -and $Matches.id -and
$Matches.version) {
                                            [pscustomobject]@{
                                                ID = $Matches.id
                                                Version = $Matches.version
                                            }
                                    }
                                }
                            }
                        }
                      :
Found Microsoft OneDrive [Microsoft.OneDrive] Version 21.230.1107.0004
This application is licensed to you by its owner.
Microsoft is not responsible for, nor does it grant any licenses to, third-party packages.
Downloading https://oneclient.sfx.ms/Win/Prod/21.230.1107.0004/amd64/OneDriveSetup.exe

  ΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆ  0.00 B / 46.5 MB
  ΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆ  27.5 MB / 46.5 MB
  ΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûê  46.5 MB / 46.5 MB
Successfully verified installer hash
Starting package install...

Installer failed with exit code: 2147747474
A higher version of this application is already installed.
At C:\Program Files\WindowsPowerShell\Modules\Cobalt\0.0.10\Cobalt.psm1:320 char:13
+             & $__handler $result
+             ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
ethanbergstrom commented 2 years ago

Do you get the same error when just using 'winget' without the Cobalt?

My guess is that's a WinGet issue, not a Cobalt issue.

Kizan commented 2 years ago

I do get an message from WinGet.exe that says "newer already version installed". I thought Cobalt would parse that message instead of throw a powershell error message. The error message I posted above is from Cobalt.psm1

ethanbergstrom commented 2 years ago

What would the expected output be, in the event of a package installation failure, other than to throw a PowerShell error that includes the output from the underlying application indicating why it failed?

I'm not aware of a comprehensive list of error messages WinGet can throw, and the Crescendo framework currently only looks at output, not exit codes.

See also: https://github.com/PowerShell/Crescendo/discussions/115

Kizan commented 2 years ago

It'd be great if the code caught the error and let me display a message to the user rather than a long-ish powershell error. Winget does output a line indicating that the local version is higher than the version in the repo.

ethanbergstrom commented 2 years ago

Which part of the error is too verbose?

This part:

This application is licensed to you by its owner.
Microsoft is not responsible for, nor does it grant any licenses to, third-party packages.
Downloading https://oneclient.sfx.ms/Win/Prod/21.230.1107.0004/amd64/OneDriveSetup.exe

  ΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆ  0.00 B / 46.5 MB
  ΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆΓûÆ  27.5 MB / 46.5 MB
  ΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûêΓûê  46.5 MB / 46.5 MB
Successfully verified installer hash
Starting package install...

Or this part:

At C:\Program Files\WindowsPowerShell\Modules\Cobalt\0.0.10\Cobalt.psm1:320 char:13
+             & $__handler $result
+             ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException

The actual error is in the middle:

Installer failed with exit code: 2147747474
A higher version of this application is already installed.
Kizan commented 2 years ago

The Winget.exe error returned is just a line or two. If you aren't interested I was just putting forth a suggestion.

Kizan commented 2 years ago

FYI the message from Winget.exe is:

"A higher version of this application is already installed."

Looks like sometimes there's an error code returned too. Not always the same, but 1603 is the most common.

ethanbergstrom commented 2 years ago

The block of PowerShell code that shows up in the output is an artifact of PowerShell 5.1 - that's just how it reports errors, and is extra long in this case due to how Crescendo invokes output handlers.

I have made a small edit in the PR I'm linking which will take some of the extra verbosity out of the message and only show what matches or comes after the keyword 'failed', but I don't think it will solve the overall concern.

Beyond upgrading to Cobalt v0.0.11, if you want more concise errors, I recommend switching to PowerShell 7 or using the Winget PackageManagement provider.

PS7 via WinGet provider:

❯ Install-Package Microsoft.OneDrive -ProviderName WinGet -Force

WARNING: Installer failed with exit code: 2147747474
A higher version of this application is already installed.
Install-Package: The operation failed. Check the WinGet logs for more information.

PS7 via Cobalt:

❯ Install-WinGetPackage Microsoft.OneDrive

Write-Error: Installer failed with exit code: 2147747474 A higher version of this application is already installed.

PS5 via WinGet provider:

❯ Install-Package Microsoft.OneDrive -ProviderName WinGet -Force

WARNING: Installer failed with exit code: 2147747474
A higher version of this application is already installed.
Install-Package : The operation failed. Check the WinGet logs for more information.
At line:1 char:1
+ Install-Package Microsoft.OneDrive -ProviderName WinGet -Force
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (Microsoft.Power....InstallPackage:InstallPackage) [Install-Package],
   Exception
    + FullyQualifiedErrorId : JobFailure,Install-Package,Microsoft.PowerShell.PackageManagement.Cmdlets.InstallPackage

PS5 via Cobalt:

❯ Install-WinGetPackage Microsoft.OneDrive

                        param ($output)
                        if ($output) {
                            if ($output -match 'failed') {
                                # Only show output that matches or comes after the 'failed' keyword
                                Write-Error ($output[$output.IndexOf($($output -match 'failed' | Select-Object -First
1))..($output.Length-1)] -join "`r`n")
                            } else {
                                $output | ForEach-Object {
                                    if ($_ -match '\[(?<id>[\S]+)\] Version (?<version>[\S]+)' -and $Matches.id -and
$Matches.version) {
                                            [pscustomobject]@{
                                                ID = $Matches.id
                                                Version = $Matches.version
                                            }
                                    }
                                }
                            }
                        }
                      : Installer failed with exit code: 2147747474
A higher version of this application is already installed.
At C:\Program Files\WindowsPowerShell\Modules\Cobalt\0.0.11\Cobalt.psm1:321 char:13
+             & $__handler $result
+             ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException