winget-cli
winget-cli copied to clipboard
Upgrading an application does not remove the existing version
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
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
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.
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.
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 it depends on whether the manifest upgrade behavior is the default or if it has been explicitly set to "uninstallPrevious".
@denelon default meaning it will install it beside the old version or do whatever the regular (non-winget) installer would do?
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.
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?
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.
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
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.
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.
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
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
WinGet 1.8 now supports targeting a specific version for uninstalling previous versions.