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

Upgrading an application does not remove the existing version

Open arbitmcdonald opened this issue 3 years ago • 14 comments

Brief description of your issue

I'm torn between this being a bug, or needing to submit a feature request for an upgrade option like --remove-old.

I had OpenSCAP 1.3.4 installed on my device. winget upgrade showed that OpenSCAP 1.3.5 was available. I ran winget upgrade OpenSCAP and it ran as expected. I think checked the output of winget upgrade and it said I needed to upgrade OpenSCAP still.

I looked at my installed programs and I could see that I had both 1.3.4 and 1.3.5 installed. So even though I had installed the new version, winget will still report that I need to upgrade.

Some questions:

  • What's the desired/intended behaviour? Is this actually a bug?
  • Is this the responsibility of the application publisher to manage this behaviour?
  • Should winget automatically remove the old version if it's used to upgrade an application?
  • Is it possible for us to have winget manage this? (I'm happy to submit a feature request)

Steps to reproduce

  • Install version 1.3.4 from here: https://github.com/OpenSCAP/openscap/releases
  • Run winget upgrade, you should see an available update to 1.3.5 (possibly 1.3.6 as it was released 12h ago)
  • Run winget upgrade OpenSCAP to upgrade the app
  • Run winget upgrade, you'll see that OpenSCAP 1.3.4 is still in the upgrade list
  • Check your installed programs, you'll see that you have both 1.3.4 and 1.3.5 (or 1.3.6) installed
  • Uninstall 1.3.4, you'll see that OpenSCAP is removed from the output of winget upgrade

Expected behavior

Upgrading an application with winget should remove the old version.

Actual behavior

The new version was installed alongside the old version, so winget endlessly installs the new version if the administrator hasn't realised that it's installed the versions side-by-side.

Environment

Windows Package Manager v1.1.13405
Copyright (c) Microsoft Corporation. All rights reserved.

Windows: Windows.Desktop v10.0.22000.438
Package: Microsoft.DesktopAppInstaller v1.16.13405.0

arbitmcdonald avatar Jan 20 '22 10:01 arbitmcdonald

Okay, I've thought about this a little more and I realise it would be really bad to remove previous versions, for example, you may need numerous and/or specific versions of Microsoft Visual C++ redistributables installed at the same time. Updating one shouldn't remove all previous versions.

Curious if this is still a suitable feature request though? --remove-previous-versions

arbitmcdonald avatar Jan 20 '22 13:01 arbitmcdonald

We have a option for this in the manifests, upgradeBehavior: uninstallPrevious (it was designed for applications which required their previous version to be uninstalled before installing the new version). We could expose this as a command line option so the user could override the default behavior for situations like you describe.

jedieaston avatar Jan 20 '22 13:01 jedieaston

I prefer the idea of adding a switch to --remove-previous-versions (this might be challenging to do the mapping to "all" previous versions). There are a few interesting user experience caveats here. The Windows Package Manager doesn't know about other programs that might have dependencies, so this would certainly be more of a "power user" feature.

Removing an earlier version of a package might also remove user customizations that don't get migrated to newer versions. I ran into this with Ultimaker.Cura.

The Windows Package Manager also doesn't have sufficient metadata to know if a package (.exe based) is going to install side by side or perform an upgrade. We've got some work on the backlog to test upgrade scenarios when we perform validation, that might be able to help in some of these cases.

I'm also still digging deeper into the dependency support scenarios. More thoughts / suggestions from the community are welcome.

denelon avatar Jan 24 '22 20:01 denelon

What is OpenSCAP's upgrade behavior without using winget? I think the least error-prone approach would be doing whatever the package defaults to when updating normally. In fact, I thought that's what winget is already doing. Is that not the case?

github-account1111 avatar Feb 03 '22 20:02 github-account1111

@github-account1111 it depends on whether the manifest upgrade behavior is the default or if it has been explicitly set to "uninstallPrevious".

denelon avatar Feb 03 '22 23:02 denelon

@denelon default meaning it will install it beside the old version or do whatever the regular (non-winget) installer would do?

github-account1111 avatar Feb 04 '22 00:02 github-account1111

Yes.

If the installer is able to detect an existing version and "upgrade" it then the uninstallPrevious would not likely be necessary.

For packages that install as a "new" program even though they are a newer version, and they don't remove the previous versions, it's up to the manifest author to determine if the Windows Package Manager should remove the previous version.

In some cases, installers require you to remove a previous version before installing a newer one. In those cases, uninstallPrevious would be required.

denelon avatar Feb 04 '22 00:02 denelon

I don't understand. I asked if it's a or b, and your response was "yes" haha. My guess is it's b?

In some cases, installers require you to remove a previous version before installing a newer one. In those cases, uninstallPrevious would be required.

What if it's required to keep a previous version?

github-account1111 avatar Feb 04 '22 01:02 github-account1111

For packages that install as a "new" program even though they are a newer version, and they don't remove the previous versions, it's up to the manifest author to determine if the Windows Package Manager should remove the previous version.

Unfortunately, there are many different scenarios. The default behavior for upgrade, unless the manifest has been written to change default behavior or the user has provided arguments to override is to simply run the installer after it has been downloaded and verified. Sometimes there are arguments that need to be passed to the installer for an upgrade (like Visual Studio). Those can also be provided in the manifest or via command line arguments.

It is possible in some cases that the user was intending to upgrade, but they used the "install" command, so in those cases the behavior may be incorrect since the upgrade keys in the manifest are ignored during the "install" flow. We're working on detecting if the package is already installed so that when a user runs "install", we can inform them and switch to the upgrade flow. If they really did mean to run install, they will be able to use "--force" to override our default behavior.

The Windows Package Manager is built to be very flexible. We're trying to meet developers where they are regardless of installer technology or behavior. That generally means, we need to define default behaviors and then provide mechanisms via the manifest, settings configured in the Windows Package Manager by the user (via winget settings), or by the user via command-line arguments to specify different behaviors.

denelon avatar Feb 04 '22 15:02 denelon

Another problem with not removing the old version, is that if you want to upgrade all installed packages, it will detect the still existing old versions and install the newest version again, although that version is already installed as well. I am not sure to what absurdities you could let it devolve, but maybe one command could install the same package twice or more.

My idea would be to introduce a second flag/option in the package like "keepPrevious". If the package calls for "uninstallPrevious", it gets always removed, if it calls for "keepPrevious", it can only be explicitly deinstalled by the user and if it has neither, the choice lies with the user (maybe via a local/global config file, maybe via a parameter).

For now, there should be another check to see, whether the new version is actually needed to be installed or already there.

Auravendill avatar Apr 29 '22 09:04 Auravendill

@Auravendill

The current plan is to check during upgrade if the "latest" available version is already installed, and essentially do nothing in this case.

If the user attempts to install and the "latest" available version is already installed, we would do nothing. The exception here is if a user specifies "--force" we would run the install again.

If the user attempts to install the "latest" available version, and a previous version is installed, Windows Package Manager would logically migrate to the upgrade flow.

denelon avatar Apr 29 '22 15:04 denelon

If the user attempts to install and the "latest" available version is already installed, we would do nothing. The exception here is if a user specifies "--force" we would run the install again.

Sounds like a reasonable way. That could solve the most annoying part of the issue. On an older machine, I tried to keep up to date, I had like 18 packages that got reinstalled each time. And some of them take quite some time.

Auravendill avatar Apr 29 '22 16:04 Auravendill

Curious if this is still a suitable feature request though? --remove-previous-versions

Although it won't remove all previous versions, in the latest pre-release there is an experimental feature for --uninstall-previous which will uninstall one previous version before installing the new version

Trenly avatar Jan 13 '23 05:01 Trenly

We've been working on the side-by-side scenarios. You could try the latest release and enable the experimental feature on:

  • https://github.com/microsoft/winget-cli/releases/tag/v1.8.924-preview

Please provide feedback at:

  • https://github.com/microsoft/winget-cli/discussions/4281

denelon avatar Apr 02 '24 19:04 denelon

WinGet 1.8 now supports targeting a specific version for uninstalling previous versions.

denelon avatar Jul 03 '24 21:07 denelon