Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

winget should not install an already installed package #929

Closed
besmirzanaj opened this issue May 5, 2021 · 23 comments · Fixed by #2655
Closed

winget should not install an already installed package #929

besmirzanaj opened this issue May 5, 2021 · 23 comments · Fixed by #2655
Labels
Catalog-Health Some scenarios related to install/upgrade/import need improvements Issue-Feature This is a feature request for the Windows Package Manager client.
Milestone

Comments

@besmirzanaj
Copy link

besmirzanaj commented May 5, 2021

Description of the new feature/enhancement

winget should check if an application is already installed before it runs the installer

Proposed technical implementation details (optional)

check for installed software (could be a registry key) before you run the install command.
example: if the winget install <software> is run once, then the next time it runs, it should prompt that the <software> is already installed and not proceed to reinstall it again.

Current implementation will reinstall the software over and over:

PS C:\Windows\system32> winget install "Visual Studio Code"
Found Visual Studio Code [Microsoft.VisualStudioCode]
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://az764295.vo.msecnd.net/stable/3c4e3df9e89829dce27b7b5c24508306b151f30d/VSCodeUserSetup-x64-1.55.2.exe
  ██████████████████████████████  68.9 MB / 68.9 MB
Successfully verified installer hash
Starting package install...
Successfully installed

PS C:\Windows\system32> winget install "Visual Studio Code"
Found Visual Studio Code [Microsoft.VisualStudioCode]
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://az764295.vo.msecnd.net/stable/3c4e3df9e89829dce27b7b5c24508306b151f30d/VSCodeUserSetup-x64-1.55.2.exe
  ██████████████████████████████  68.9 MB / 68.9 MB
Successfully verified installer hash
Starting package install...
Successfully installed
@besmirzanaj besmirzanaj added the Issue-Feature This is a feature request for the Windows Package Manager client. label May 5, 2021
@ghost ghost added the Needs-Triage Issue need to be triaged label May 5, 2021
@denelon denelon removed the Needs-Triage Issue need to be triaged label May 5, 2021
@denelon
Copy link
Contributor

denelon commented May 5, 2021

There may be cases where a subsequent install is intentional. A user might be attempting a downgrade scenario.

We might also prompt "Did you want to upgrade?" or something like that as well.

@besmirzanaj
Copy link
Author

besmirzanaj commented May 5, 2021 via email

@denelon
Copy link
Contributor

denelon commented Nov 9, 2021

We should notify the user that the package is already installed and inform them it's possible to use "upgrade". We will still likely keep the --force option for install, and may add this to upgrade. There are scenarios like an unknown version that might be helped out in this case. It might seem a bit strange in the case it's actually a downgrade. That might be a case where we can't detect when the version is unknown, but if the version is known, we might recommend using force as well.

@denelon
Copy link
Contributor

denelon commented Nov 10, 2021

How about:

The current version is installed on the system:

>winget install "visual studio code"
Warning: Microsoft Visual Studio Code [Microsoft.VisualStudioCode] is already installed.
No upgrade is available.
>

An upgrade is available:

>winget install "visual studio code"
Warning: Microsoft Visual Studio Code [Microsoft.VisualStudioCode] is already installed.
Upgrading Microsoft Visual Studio Code [Microsoft.VisualStudioCode]
Found Microsoft Visual Studio Code [Microsoft.VisualStudioCode] Version 1.62.1
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://az764295.vo.msecnd.net/stable/f4af3cbf5a99787542e2a30fe1fd37cd644cc31f/VSCodeUserSetup-x64-1.62.1.exew
  ██████████████████████████████  76.2.8 MB / 76.2 MB
Successfully verified installer hash
Starting package install...
Successfully installed
>

We could optionally add a setting for the default behavior. The default setting would be to perform the upgrade, users could also specify not automatically running the upgrade. In that case, the user would be informed an upgrade is available, but they would need to run the upgrade command themselves in that case:

>winget install "visual studio code"
Warning: Microsoft Visual Studio Code [Microsoft.VisualStudioCode] is already installed.
An upgrade is available.
Found Microsoft Visual Studio Code [Microsoft.VisualStudioCode] Version 1.62.1
>

@besmirzanaj
Copy link
Author

I like this one. makes more sense

@denelon
Copy link
Contributor

denelon commented Nov 10, 2021

We could have three settings "automatic-upgrade", "inform-only", and "prompt" which could give a [Y] | [N] option for the upgrade. Note this would also be impacted by the future work for package pinning.

@keentext

This comment has been minimized.

@vedantmgoyal9

This comment has been minimized.

@gerardog
Copy link
Contributor

gerardog commented Aug 2, 2022

+1 here.

My scenario: I'm creating my own windows dotfiles repo. I would like it to have a declarative definition of my environment. Kind of a poor's man puppet/cheff recipe. I thought it would be trivial with winget and a install.ps1 :

winget install Notepad++.Notepad++
winget install Docker.DockerDesktop
winget install minikube
(...)

The thing is, Docker may require a restart, which breaks blocks minikube install. That is something I can handle by manually re-running the script. Nonetheless, every already installed app will attempt a reinstall, including the 500mb Docker wich gets downloaded again and it takes some time...

My script is meant to install, not upgrade the components. To upgrade I already have winget upgrade command.
Others mentioned a command to install or upgrade winget install --upgrade. I would find that usefull too.

These are the semantics that feel natural to me and would allow me to script my environment:

  • winget install pkg: Install if not installed (never upgrade):
  • winget install pkg --force: Reinstall, or upgrade (IMO)
  • winget install pkg --upgrade: Install only if not installed, upgrade if newer available, do nothing if already on latest..
  • winget upgrade pkg: Upgrade if installed, fail if not installed.

@lorthris
Copy link

+1 here.

My scenario: I'm creating my own windows dotfiles repo. I would like it to have a declarative definition of my environment. Kind of a poor's man puppet/cheff recipe. I thought it would be trivial with winget and a install.ps1 :

winget install Notepad++.Notepad++
winget install Docker.DockerDesktop
winget install minikube
(...)

The thing is, Docker may require a restart, which breaks blocks minikube install. That is something I can handle by manually re-running the script. Nonetheless, every already installed app will attempt a reinstall, including the 500mb Docker wich gets downloaded again and it takes some time...

My script is meant to install, not upgrade the components. To upgrade I already have winget upgrade command. Others mentioned a command to install or upgrade winget install --upgrade. I would find that usefull too.

These are the semantics that feel natural to me and would allow me to script my environment:

  • winget install pkg: Install if not installed (never upgrade):
  • winget install pkg --force: Reinstall, or upgrade (IMO)
  • winget install pkg --upgrade: Install only if not installed, upgrade if newer available, do nothing if already on latest..
  • winget upgrade pkg: Upgrade if installed, fail if not installed.

this seems like the best solution to me.

  • Default behavior doesn't needlessly install already installed apps
  • You can re-install if you need (troubleshooting? e.g downgrounding? can use --version to specify in combination with --force?)
  • You can guarantee by scripts end (I also use winget in various scripts) that the image a) has every program installed, b) are all up-to-date, c) doesn't take any longer then needed and d) no settings files etc for the apps are over-written (which currently happens for some apps when installing over the top of the currently installed app)

in before "you can use a combination of winget list, winget upgrade and winget install in a script to achieve this already'

yao-msft added a commit to yao-msft/winget-cli that referenced this issue Sep 20, 2022
…es to winget install and winget upgrade flow.md
yao-msft added a commit to yao-msft/winget-cli that referenced this issue Sep 20, 2022
…es to winget install and winget upgrade flow.md
yao-msft added a commit to yao-msft/winget-cli that referenced this issue Sep 20, 2022
…es to winget install and winget upgrade flow.md
@db2222
Copy link

db2222 commented Oct 10, 2022

Just in case somebody needs a workaround for a script:

set app=Microsoft.DotNet.Runtime.6
winget list %app% | findstr /c:"No installed package found" /c:"Es wurde kein installiertes Paket gefunden" > nul && (
    winget install %app%
) || (
    winget upgrade %app%
)

Change it to your wanted app.
Also you have to change the findstr search text if you need a different/further language than English/German.

Of course it would be way better if winget had a simple flag or command to avoid such mess 😉

@fernandog
Copy link

If apps don't set the "DisplayVersion" in Win Registry, isn't possible to winget to get the version from the EXE using PowerShell command?

image

@denelon
Copy link
Contributor

denelon commented Oct 14, 2022

It is possible to get the "file version" from an .exe, but that doesn't always correlate to the registry entries that are used to display package versions in Windows Apps & Features. That could also lead to other unintended consequences when the package does decide to write something to the registry. There are also cases where there is a "marketing version" for a product that publishers prefer to display to users. Sometimes a program will also display a different version itself than the file version.

There are just too many edge cases that lead to unreliable or confusing behavior for users which is why we defer to the version reported to Windows Apps & Features, and we allow a different "marketing version" to be displayed in the manifest than the version reported in the registry. The .NET packages are a perfect example of that use case as well.

@besmirzanaj
Copy link
Author

in my opinion the moment an app is installed with winget (just like choco) a version is stored either in a manifest file or in the registry so that the next time winget will parse the app version prior to decide what to do with the install option

@Masamune3210
Copy link

The issue with that is it doesnt take into account anything that may happen outside of winget between runs, meaning things can get out of sync quite fast depending on the installed apps and their hastiness of automatically updating or users not bothering to use winget and just updating something manually. It would basically lock people into only using winget or never having winget work correctly

@gerardog
Copy link
Contributor

in my opinion the moment an app is installed with winget (just like choco) a version is stored either in a manifest file or in the registry

In a way, it already does that @besmirzanaj. When you install a store app, the store has its's own registry. If it is a winget manifest, then is tracked in the "Add/Remove Programs" windows registry. I think there is no technical barrier preventing to implement this. The problem is the different visions & expectations of what each command should do between previous version and users coming from different ecosystems, including former winget versions.

@yao-msft can we take a look at the new spec?

@denelon
Copy link
Contributor

denelon commented Oct 21, 2022

TLDR;

If you call install <package> and a version of that package is already installed, we will switch to the upgrade flow.

That should also be able to honor the pinning feature currently in progress:

Adding "--force" will essentially force the install flow rather than switching to the upgrade flow.

@gerardog
Copy link
Contributor

If you call install and a version of that package is already installed, we will switch to the upgrade flow.

That's disappointing. Wasn't this issue about how winget install should fail if the app is already installed? (no matter which version).

I already explained myself in this comment?

@denelon
Copy link
Contributor

denelon commented Oct 21, 2022

Muscle memory seems to be driving this behavior more than anything else. I'd like to help people fall into the "pit of success" here. If a user is asking for a thing to be installed, and the latest version is present (or in the future, the pinned version is present) then it would essentially be a "no-op". If the package isn't pinned, and it's an "older" version, then the action would be upgrade.

We could certainly consider a setting to change the behavior. A user could essentially say "I don't want an upgrade if any version of a package is installed and I try to install it again", but the default would be if a user tries to install an existing package, WinGet would upgrade it.

@denelon
Copy link
Contributor

denelon commented Oct 21, 2022

If we had such a "setting", then it makes sense to also have an argument that could override the default behavior or the behavior in a user's settings.

@gerardog
Copy link
Contributor

A setting is persistent, which is not really script-friendly, or at least a second class citizen. Would force me to do read-setting; store-somewhere; set-new-setting; try{ install } finally{ set-previous-setting } in each script. Not really Ctrl-C friendly.

I may settle with an argument like winget instal XX --no-upgrade.

  • Choco and scoop install fails if already installed.
  • Apt-get install XX does upgrade if installed, but provides a --no-upgrade option.

@denelon
Copy link
Contributor

denelon commented Oct 21, 2022

I like the idea of following prior art to avoid some muscle memory confusion "--no-upgrade" makes sense as an argument to "override" settings if they are different in my opinion.

@yodog
Copy link

yodog commented Oct 25, 2022

i dont get why reinvent the wheel.
if i want to install something, just return "already installed. bye".
thats all. no need to trigger a upgrade or error message.
makes our scripts easier.

currently checking each package before installing...
winget list Git.Git || winget install --accept-package-agreements --accept-source-agreements --exact --silent -q Git.Git

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Catalog-Health Some scenarios related to install/upgrade/import need improvements Issue-Feature This is a feature request for the Windows Package Manager client.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants