You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
winget should not install an already installed package #929
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
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.
>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
>
Reacted by Besmir Zanaj, Paul Jezek, Aki, James, Raffaele and zengqinglong
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.
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.
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
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
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 Besmir Zanaj (@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.
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.
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.
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.
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.
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
Activity
denelon commentedon 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 commentedon May 5, 2021
denelon commentedon 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
--forceoption 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 commentedon Nov 10, 2021
How about:
The current version is installed on the system:
An upgrade is available:
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:
besmirzanaj commentedon Nov 10, 2021
I like this one. makes more sense
denelon commentedon 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 commentedon Nov 25, 2021
vedantmgoyal9 commentedon Nov 25, 2021
10 remaining items
fernandog commentedon Oct 14, 2022
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?
denelon commentedon 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 commentedon Oct 21, 2022
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 commentedon Oct 21, 2022
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 commentedon Oct 21, 2022
In a way, it already does that Besmir Zanaj (@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 commentedon 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 commentedon Oct 21, 2022
That's disappointing. Wasn't this issue about how
winget installshould fail if the app is already installed? (no matter which version).I already explained myself in this comment?
denelon commentedon 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 commentedon 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 commentedon Oct 21, 2022
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 reallyCtrl-Cfriendly.I may settle with an argument like
winget instal XX --no-upgrade.Apt-get install XXdoes upgrade if installed, but provides a--no-upgradeoption.denelon commentedon 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 commentedon 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.Gituse --force to not fail if julia already exists