winget-cli: Installing a package doesn't add it it to path
Brief description of your issue
Installing a package doesn’t add it it to path
Steps to reproduce
- Install Vim using
winget install Vim
- Try to run it using
Vim test.txt
Expected behavior
Vim should open the file if it exist or create a new file.
Actual behavior
Vim : The term 'Vim' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included,
verify that the path is correct and try again.
At line:1 char:1
+ Vim .\test.txt
+ ~~~
+ CategoryInfo : ObjectNotFound: (Vim:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Environment
Copyright (c) Microsoft Corporation. All rights reserved.
Windows: Windows.Desktop v10.0.19041.450
Package: Microsoft.DesktopAppInstaller v1.10.42241.0
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 151
- Comments: 143 (32 by maintainers)
I just tried winget for the first time on a brand new windows 11 system from dell and encountered this.
winget install whois
,whois
and receivedwhois : The term 'whois' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
This is completely unacceptable and an absolute non-starter for a package manager. this is the application level equivalent of installing an operating system without adding it to the bootloader. fixing this should be priority 1. thank you
@matifali this path problem is not because of winget-cli.
The actual installer of vim does not add vim directory to the path. So this is not an issue of winget-cli.
Being able to easily install vim with winget should be a core use case of winget.
I’m very frustrated
Winget is shockingly close to being one of the most valuable programs on windows. However If a console program can’t be called after installing it, it should not be included in the packages. Winget is a terminal command, and the things it installs should also be accessible. If I can install console programs programmatically and can’t use those programs programmatically it really has no value in any sense. This is bundled with the paid product Microsoft Windows™ and provides critical functionality that prior Windows™ desperately lacks. I was embarrassed at work when I told coworkers about winget. Even git didn’t work and I have no clue how to make it work.
lol.
So I’m a complete idiot. How can you figure out where vim actually installs. I’ve tried winget list vim and can’t figure it out. Do I look at the source. Same issue with winget install git by the way.
Great news!
https://blogs.windows.com/windows-insider/2024/02/14/announcing-windows-11-insider-preview-build-26058-canary-and-dev-channels/
Search for “winget” on that page.
Note: This has not been implemented in PowerShell.
This issue’s been open for 3 years and I get emails for this thread frequently. The conversation keeps going in circles about how it’s not the role of the package MANAGER to manage the dang package! This is far from true of EVERY other package manager I have ever used for any system or language, ever. I have never had to go hunt things down after they were “installed” because they’ve always worked as expected. The only one that’s not in line here is winget, and it makes me think about POLA (Principle of least astonishment).
see also
I know this isn’t actual law, but having to play find the needle in the haystack with software I got through winget isn’t what I expect from a package manager - the package manager is supposed to let me pick a package from a repository, install it, and be able to use it after install. Winget does 2/3 of those things. As a user, I couldn’t really care less how this is handled semantically; I just want those programs to be callable! Not a single thing I have ever installed through winget has been callable after install even if I opened up a new shell. I’ve had to look for Every package and add them all to path myself, --info is supposed to show me install locations, among other things, and I’m not even seeing my package in those directories, --location is supposed to let me at least pick the location the package is installed to and that didn’t work for me! So now here I am, having to play find the needle in the haystack with ffmpeg and thinking about POLA, and this specific Issue.
The thing I really admire about technology is that there’s never only one perfect way to solve an issue, there are always multiple options that can be used to achieve a given goal. This is true on both ends, you have multiple options you can try to work with, and I have other package managers I could try that work as expected. I’d rather have SOMETHING that’s good, than wait around forever for something to be perfect. I don’t need perfect, and no one here is asking for perfect or really even being too picky about the implementation.
Anecdotally, I’m using a different computer and the Chocolatey package manager was FAST to install, it installed ffmpeg quickly for me, and I didn’t even have to start a new session to call it. This is a package manager working as expected, this is the kind of result I want to see. Chocolatey used a shim, I do not care that they used a shim, they didn’t get bogged down with the semantics like we’re seeing here they just did Something! Seeing how fast and simple Chocolatey was to setup/use, I don’t really see myself coming back to winget and am just going to put Chocolatey on all my home and work systems for future use, and if asked about a good Windows package manager that’d likely be my go-to because yeah if I’m being honest with them and knowing what they expect from a package manager why would I, or anyone, recommend winget over anything else that does what people expect a package manager to do.
I want to be sympathetic here, but every time this Issue looks like it’s going in the right direction and we landed on SOMETHING to try, it gets steered back to the position that winget is not responsible for making things callable after install - and that this is the job of the package maintainers themselves. I don’t really have the energy to care about this anymore given I found a good solution, but figured this feedback is important to share nonetheless. There is a lot of valuable user feedback and genuine good faith attempts at trying to find a solution in this thread that is not being fully appreciated and these people are working with you for free and unsolicited because they want this to succeed. I do too, but I can’t really wait for it and I’m definitely not going to argue for it when Chocolatey is right there.
Three separate things that would probably make this whole situation more workable for end users, besides actually addressing the problem in question, would be 1.) show people WHERE any given package is getting installed so if it’s not callable afterwards we at least know where to look exactly so we can fix it ourselves 2.) don’t call winget a package “manager” if it can’t fully commit to being one, can’t complain or compare it to a PM if it’s not trying to be one, or 3.) fully lean into it being on package maintainers to ensure a portable/MSIX version of their package is added to the repo for predictable outcomes, and in doing so tighten your standards on what it takes for a package to be listed in the repo.
After having gone through the entire thread I’m assuming every single program I’ve ever tried downloading through winget wasn’t portable and led to them all ending up in random locations and giving me an extremely poor UX. The poorest package management UX I’ve ever had to date!
Also not helping with the overall reception here is it’s not clear who on this thread is actually a winget dev and who is just playing devil’s advocate and speaking for/over winget devs (or defending MS) - neither of which they have to do because everyone who is raising this as a concern wants to see a built-in Windows package manager that’s on-par with any other run-of-the-mill package manager.
Yes, Linux-based ones will be mentioned because they’re the most immediately recognizable - but you also have working Windows-based ones being mentioned by name because people want it to work! Pedantry isn’t productive and if you’re not actually on the dev team are just drawing more ire towards them, lack of visibility into what’s actually happening with this Issue doesn’t help, and as an end user my trust and interest in this product is pretty burnt :^} this exact Issue IS a really big deal and IS a major expectation of anyone who has used a package manager before, regardless of what’s being argued here. winget is the outlier full stop.
This is a very real example of someone who leads the IT/*Admin team at an organization falling out of this because of all the friction and inconsistency that goes into trying to use it, as has been warned about multiple times throughout the thread. I am validating those people and saying they are right.
Thanks, I came from linux and is used to installing packages with
apt
command. So I was expecting the same behaviour withwinget
.We’re working to get dependencies out with WinGet 1.6 (ETA end of September). A couple of weeks after that we will start automated validation with dependencies in earnest.
Updated: WinGet 1.6 supports dependencies. With the latest version of WinGet you should be able to:
@doctordns: it’s true that there’s not a great way for a separate process (
winget.exe
) to modify the environment block of a parentpowershell.exe
process, but as alluded to in several places on this Issue, there are other ways to deal with the problem. In particular, I proposed a solution in this comment, including a concrete list of design constraints which led me to that solution, and actual code you could put on your system to try it out.(It’s totally understandable that one could miss that comment; this Issue is huge, and I had to click through multiple “show hidden items” folds in order to find that comment again.)
I took the liberty of making my idea easier to consume by publishing it as, you guessed it, a winget package. 😄
It requires admin access to install, which is unfortunate, but even so I think it could make things a lot more convenient for a lot of people, so I went ahead with it. You can try it out by:
(that is for
pwsh
, but it also works forcmd
; just don’t paste the#
comments, of course)(More info here: https://github.com/jazzdelightsme/WingetPathUpdater)
My package is not an ideal solution. Besides requiring admin, you have to know that you need it–having a solution in package form does not help unless you have the package, and I expect most people will not know that they need this package.
Just to head off the conversation “why doesn’t winget just ship this ‘in-box’?!”: the winget team has more constraints than I do (see caveat at the beginning of my Design comment), so I doubt they would find it feasible. However, they are aware of this package’s technique (and I know they carefully read and discussed my Design comment), so hopefully it is helpful to them. And I hope my package is helpful to people in the meantime.
Edit: oh, and special thanks to @denelon and @stephengillie for helping me get my package manifest working!
Edit 2: Oh crud; my first demo used “
winget install vim.vim
”… but I had tested on a not-clean system. It turns out that the problem with thevim.vim
package is that it does not updatePATH
at all–even opening a new console window does not help. Sigh. So I updated the demo to usenvim
.Edit 3: on a totally clean VM, nvim “launched”, but didn’t really run: it depends on the VC runtime, but doesn’t distribute it (installer bug, IMO). So I added “
winget install Microsoft.VCRedist.2015+.x64
” to the demo.As I know,
winget
don’t add to PATH automatically. But if the installer itself have ability to add its exe to PATH that meansSwitches
have problem. I’m gonna look at it.I’m look at it and vim installer don’t have any installer arguments (and there is no installer option to add PATH too). You have to add yourself until this ability comes to
winget
. There is some feature requests about this issue. It’s gonna be added.Have a nice day! 🥂
+1, I was delighted to learn that a Windows package manager exists but alas. The minimum expectations I have for a package manager are:
The third point is what I did not see after installing Vim. Since I am only installing a single package it is feasible to manually add it to path but winget still has a ways to go as a go-to resource.
I do think it is the role of the package manager to add installed packages to path automatically and like this suggestion if it’s compatible with the other points
Appreciate the hard work on this and looking forward to seeing winget reach its potential! Just throwing in my two cents to show that this is a looked-for feature and there is community interest in winget.
I don’t know why we keep going back to this. I understand how the issue’s title could give the initial impression that winget needs to add stuff to PATH, but if you read their full message, the only thing OP wants is the following to work:
And this behaviour can be achieved using shims. scoop does it today. It is not some novel problem that we have to rewrite the OS from scratch to fix.
So, please stop bloating the thread about why something we never needed in the first place can’t be done.
When I don’t care about a feature, I just ignore the GH issue suggesting it, because why not have it if it will be useful to someone, right? That is unless it would introduce some undesirable behaviour that I rather not see in the product. Does winget implementing this feature have any downsides you’re worried about that we are not aware of? Would it negatively affect how you use winget in any way whatsoever? And if not, what value are you trying to add here?
“I’ve been using Windows before you were born, and I never needed it” isn’t an argument against this feature - the only thing it tells is that there are people who can live without it, and don’t get me wrong, that still is valuable feedback, but does it really need to be repeated under every message that justifies this feature? We heard your opinion about why you don’t need this, but we all have different needs.
A long response but while the POLA is an interesting justification, Snover’s First Law trumps it. To ship is to choose and in 3 years the Winget team has indicated no interest in implementing this, and almost zero support elsewhere. And o see zero interest from those who could implement it. In my experience guilt tripping rarely works.
But if you want it, then explain how it could be implemented. I know of no way running an executable in PowerShell that can cause the environment block refreshed (and $profile to be reexecuted). And even if it could be, it would seem to be a security hole.
I see little hope of winget doing this on its own. You would need to change PowerShell and Windows Powershell. And I see zero chance of updating powershell to implement this (and an even lower chance of backporting it to Windows PowerShell. I could be wrong, but I simply see inadequate support.
Rather than populate your PATH like Chocolatey, winget should add shims like Scoop(UWP also has this feature) https://github.com/microsoft/winget-cli/issues/361
I hope you appreciate “I never needed it in N years 😃 let’s close it as Won’t Implement” sounds way less reasonable than “This requires changes outside winget, so we’re blocked until that happens”.
With shims! Manifests can allow specifying executable names that we want in PATH, and winget can put shims of those executables to a folder that’s already in PATH. That’s a problem solved years ago by choco and scoop.
I left https://github.com/microsoft/winget-cli/issues/549#issuecomment-1369959015 here 7 months ago. I’m not sure what’s the state now, but we needed two things back then:
I see we also have #361 to track shims but it doesn’t seem to have received any traction.
This is the exact attitude that bothers me so much. “It’s always been that way so we should just leave it be.” We’re trying to improve a product in here; if you’re going to be a nay-sayer go somewhere else. Just because you never use it doesn’t many no one else does.
And what you’ve done in the past is irrelevant. We also use to trust SHA-1 and didn’t have MFA. Times change and until winget makes feature parity, it will be another excuse for linux fans to reject Windows as a competitive option.
I’m NOT suggesting we forgo security to make it work; I just think it’s ridiculous to look at a problem and say “nope, can’t be done.”
If you come to the conversation with a list of problems and no solutions, you’re just a complainer.
Why is winget different in this respect to practically all other package managers? Every user is going to expect winget to add the package executable to the path. Not doing that is tantamount to a bug, especially from the perspective of a user.
@Witchilich Sorry to jump in. I just wanted to note that Chocolatey brought about the idea of shims not to clutter your PATH - it existed long before Scoop was created as a concept called batch redirects. Later we moved to shim exes. Luke thought shimming was great and added it to Scoop. Just want to make sure the credit is in the proper place on shims.
References:
I think your confusion might be in that Chocolatey might defer to an installer as well, which might put things on PATH. Scoop doesn’t use the installer at all, it just unpacks, so the shims are much more necessary. Chocolatey’s docs on this - https://docs.chocolatey.org/en-us/features/shim
In the meantime, use the --interactive flag and click the .bat file checkbox per https://github.com/microsoft/winget-pkgs/issues/656#issuecomment-1284415659
winget install --id vim.vim --interactive
“Near future” is subjective. My preference is to have an experimental feature before just rolling it out to “everyone”. We’re looking at the challenges with Windows PowerShell vs. PowerShell 7 currently. I’m expecting we will make incremental progress with this one.
I’m also looking at the nuances between how we do experimental features in WinGet and how they are done in PowerShell. I want to make sure we’re following the right idioms between the two types of experiences (Windows CLI vs. native PowerShell).
There are lots of 👍 on this Issue so it does bring more priority to this issue compared with many others.
@Masamune3210 A hack would be vastly better than the abysmal and confusing experience we have. If you’re going to pass the buck to a different team, you should link to the related issue. The closest I could find was an improvement for refreshing environment variables, which could be useful to us in implementing a fix but the fix needs to happen from winget’s side. Most of the time people are not refreshing the environment variables, so it does not make much sense to do it constantly. Additionally the proposed solution of kicking the responsibility to terminal does nothing for people using windows server.
https://github.com/microsoft/terminal/issues/15102
@doctordns This is almost always false. Many problems are not addressed not because they are hard, but because they are lower priority. Software development has a triage process and breaking bugs and issues get first priority. This can mean that important but not required usability improvements go unaddressed, and if long enough even forgotten. User experience issues tend to be the items that are disruptive to use, but nonetheless never get fixed. We blame the users for being incompetent and move on. This sounds great until we ourselves are the users, and we ourselves have to remember little strange quirks for 80 different small applications that we use once every 3 years. I could understand that maybe it doesn’t refresh env on git-bash or whatever but it should definitely work on powershell.
@Hathoute If your users are routinely falling into a confusing trap, you should fix it. Winget in windows is supposed to work in an unsurprising way. This behavior is very surprising, as this thread indicates. We can say this is how it does work, but it is not supposed to work this way.
I agree with this. I forgot how powershell and terminals in windows are supposed to work, hence why I (and probably most people) got here.
If it were easy, we;d have had a solution years (decades?) ago. I would argue winget is working as designed and this is not a bug.
The shims have the advantage of not needing to update every program’s environment after installing a package. This would help us implement CI/CD pipelines with Winget.
@denelon This is indeed good news, but many programs don’t add themselves to the PATH at all - we still need a solution for these (expecting all programs to remember to do this isn’t realistic).
It’s surprising anyone needs convincing that being able to do the following is useful:
Yes, having to start a new shell after I install an app won’t kill me.
Yes, my PS script having to do
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
whenever it needs to run an app it just installed won’t kill me.But we can all see why not having to do these things would be convenient, right?
With that said, the claim that winget is an unusable mess just because the PATH updates are not immediately visible within the current session doesn’t really resonate with me. The main functionality of a package manager is to manage packages, i.e., find, install, update, and uninstall them. winget does all these, and the fact that it’s not as convenient as others yet doesn’t make it alpha.
So, I disagree with both the “this feature is useless” and the “this app is useless” arguments. winget is great as it is but there’s always room for improvement, and this one would be a pretty big improvement for how I use winget.
Literally every other package manager inside or outside of windows works in this way, so it’s surprising to nearly everyone who has experience with the thing.
Here’s a full write-up of the key design constraints that I observe for a solution to automagically update the PATH environment variable in a user’s shell, along with my suggested approach.
TL;DR: if you want to try my suggested solution, put the files at the bottom of this post into your
C:\windows\system32
directory, and as long as you always say “winget
” instead of “winget.exe
”, things will probably work as you expect (environment will be updated) incmd.exe
,powershell.exe
, andpwsh.exe
.Also, first some important caveats:
system32
folder, I’m pretty sure the DesktopAppInstaller package can be installed without elevation, so they likely will not want to use that location). Though my proof of concept works great for things like nvim, I know that they face much more complicated situations/packages, too.With all that said, let’s jump in.
The crux of the problem is that environment variables need to be updated in the user’s shell, which is going to be a different process than the
winget.exe
process. This leads to the main constraint for any possible solution:Requirement 1: somehow, someway, there will need to be code that runs in the shell process.
Where does that code come from? One could imagine that it could be built into the shell itself: for instance, if
pwsh.exe
itself created a hidden window, in order to listen forWM_SETTINGCHANGE
messages; upon receipt of said message, it could refresh its environment block.But there are some problems with that:
WM_SETTINGCHANGE
message.winget.exe
blindly broadcast it.cmd.exe
andpowershell.exe
are incredibly unlikely to even consider such a change. They are frozen.So in my mind that idea (code being built in to the shell itself) is a non-starter.
More about the “diff” problem: it is absolutely not a simple operation to “just refresh the PATH environment variable”. The PATH variables (I’m thinking specifically of PATH and PSModulePath) are stored in the registry, but you can’t just read the current registry value and say “well, that’s the current path!”, because it’s not. Many shells and environments, including
powershell.exe
andpwsh.exe
, modify their PATH environment variables at runtime, depending on myriad and complicated factors. (Want a headache? Just try to figure out howpowershell.exe
andpwsh.exe
heuristically update PSModulePath at runtime (it can become… problematic).) And it’s not just the shells themselves; many shell-based “operating environments” also perform heavy and critical customization of PATH-related environment variables. So you absolutely cannot “just read the current values from the registry” and apply them in-memory. Doing so would break approximately a million things.So how could we update the environment, in as safe and non-breaking a way as possible? The critical thing is to not mess up any in-memory customizations, so ideally we just tack on the bare minimum of “what actually changed” onto the very end. (It’s possible that an installer does something super fancy, and purposefully updates
%PATH%
to stick something new in the middle, before some other paths; but I think that’s a rare case, and getting it wrong by updating the current process’s PATH to add the new thing at the very end is at least still not disruptive to any other existing in-memory customizations.)This is what gives rise to:
Requirement 2: There has to be a “diff”: we need to know what actually changed, so we can add just that to the end of the current, in-memory value.
So we have to compare a “before” and “after”… and with the
WM_SETTINGCHANGE
broadcast there is no clear “before” point. Trying to compare an in-memory, potentially highly customized value to what’s in the registry, with no frame of reference, is doomed to be extraordinarily fragile and impossible to get completely right. Like a three-way merge without the “base”.Okay, back to requirement 1: we have to have code that runs in the shell process. How can we do that? I see only two options:
CreateRemoteThread
API is one of those scary APIs with documentation that says things like “the application can deadlock if the thread attempts to obtain ownership of locks that another thread is using”. Given that we have a narrow list of shell processes to target, it could probably be made to work… but it’s a pretty serious thing to go injecting code into an unsuspecting process..cmd
/.bat
script. b. For PowerShell: a.ps1
script. c. Bash: a.sh
script. d. Etc. e. Because winget is Windows-specific, just handling cmd and PS is good enough; who in the world is running winget commands from bash, amiright? 😄Okay, so we’re going to have a script.
This brings us to the last piece of the puzzle: how is the [shell-specific] script going to get executed in the proper shell process?
Winget.exe
can’t do it directly (and don’t sayCreateRemoteThread
again)…Easy: just have the user do it! 😄
We train people to just run “
winget <arguments>
”… but that does not have to directly bewinget.EXE
. If we havewinget.ps1
andwinget.cmd
, which come beforewinget.exe
on the%PATH%
, then when you are incmd.exe
, and you run “winget
”, you will runwinget.CMD
; when inpwsh.exe
, you will getwinget.PS1
.And here’s what the script will do:
winget.exe
, passing through all arguments (%*
/$args
).Et voilà!
(This is actually a pretty standard trick; to wrap things in a script wrapper for various reasons.)
If you want to try this out, a convenient, guaranteed-to-exist-and-be-on-the-PATH-and-come-before-the-
windowsapps
-dir path isC:\windows\system32
. So you can put the script files below into system32 as an easy way to evaluate this, but remember that this is probably not an attractive “real” solution for the winget package (which means somebody needs to do some work to arrange for a different, user-specific (so it won’t require elevation) path to be on the%PATH%
, before thewindowsapps
dir (where thewinget.exe
command is found).(Also, note that you don’t actually need the
.Tests.ps1
file; that’s just test code, which is convenient if you want to play around with it. Note that it requires you to install Pester v5.)Script files:
winget.cmd
:winget.ps1
:wingetHelper.ps1
:wingetHelper.Tests.ps1
:I would really like some movement on this. This issue defeats the point; if I cannot immediately use a command after installing with winget, then I’m not even going to waste the time. It’s easier for me to just click through an msi installer.
@denelon I don’t know how you gonna handle this but something like this will be good I think:
location:
variable as keyword to all manfiests files and install them under “…\winget-pkgs\$pgkname” to easily find winget-pkgs.location:
keyword.shortcut:
keyword to manifests.createshortcut:
keyword (can be overridden withwinget install vim --shortcut y|n
)winget-shortcuts
name with powershell script after each successful installation according tolocation
andshortcuts
from manifests. (I don’t know how to create environ vars from powershell and I’m too lazy to right now to find it. 😆)In the end it turns something like this (example for vim manifest):
Completely missing the point? And what exactly do you think the point is here? Because to me the point of winget is to make feature parity with other major OSes and moreover to make the user experience easier. So what Windows has historically done is irrelevant and what other OSes do is exactly the point.
And further, why even argue against this improvement? If it gets implemented, you lose nothing. There’s obviously a lot of people who are confused by this, so it must be a worthwhile addition.
Neither chocolatey nor scoop regenerate the environment block, and anything outside of on Windows is completely missing the point.
(I forgot to add: a small downside to the “script wrapper” approach is that if someone runs “
winget.exe
” instead of “winget
”, then they don’t get the magical path-refresh behavior. But there’s a very good upside to this: it means that if there were some targeted situation where you didn’t want path refresh, you could avoid it by just runningwinget.exe
instead.)I mean it’s not impossible to do, Winget could do it.
Hey all, I’ve been talking with the team about adding some additional information after installing a portable package. The behavior depends on a few different factors. We’re looking at better messaging as a hint to let the user know if they need to restart their shell/terminal or not.
In most cases, the first portable install will require the shell/terminal to be restarted. For portable packages installed in user mode (and developer mode disabled) the shell/terminal restart will most likely be required. For subsequent portable packages installed in admin mode the shell/terminal restart will most likely not be required. For subsequent portable packages installed with developer mode enabled the shell/terminal restart will most likely not be required.
In this example (Vim), and with many “installers”; restarting the shell/terminal will be necessary. In many cases with upgrade (assuming it’s an upgrade to an existing package and not a side-by-side installation); restarting the shell/terminal will not be necessary.
We don’t have a good reliable mechanism for dealing with a refresh of the Path environment variable as we could be called by any number of shells that all deal with environment variables a bit differently, and we aren’t given the context necessary to figure out exactly what needs to be done in all cases.
We do have additional affordances possible with PowerShell and the WinGet cmdlets that may make it better, but that’s not the case with cmd.exe and many others.
@Okeanos It would be a good idea if it worked that way out of the box. It’s the only package manager I’ve ever seen where you must provide bespoke override flags for individual packages to install as expected. Packages should work without --override or they should be removed until they are fixed.
@Masamune3210 That’s technically not quite the same issue, since the screenshot you show is for installing Chocolatey itself. Once you’ve installed it, it provides a function (aliased as
refreshenv
) to reload your env vars, and the installation text output prompts the user to run it after something new has been installed.FWIW, from a user perspective, I have no problem with junctions. It’s a bit annoying that they require admin permissions to create (IIRC), but otherwise I’ve been using them without issue since…probably 2015ish, I think.
I’ve seen a couple of examples at Stack Overflow like: https://stackoverflow.com/questions/14381650/how-to-update-windows-powershell-session-environment-variables-from-registry
@voronoipotato thanks for the detailed feedback here.
We’ve been discussing several challenges associated with required environment variables like “path”. We implemented support for path in the portable install flow, but we’re still dependent on the package installers to handle this correctly today for other installer types. Part of the “upgrade” challenge is also associated with what type of an installer is actually being used.
MSIX packages upgrade natively (although there are still some bumpy experiences like upgrading winget by running
winget upgrade "App Installer" -s msstore
). For MSI “upgrades” we use the Product Code or the Upgrade Code to upgrade the “same” package. Traditional “.exe” based installers are essentially still much more challenging as they might do anything.As there aren’t graceful ways to deal with switching installer technology, we prompt the user when the installer type changes, and inform them that they need to uninstall the version on their system before installing the newer version. We’ve added keys to the manifest for “uninstallPrevious” when we know the earlier version should be removed, but in some cases, a side-by-side install is “by design”.
We’re adding extra metadata to manifest so we know what the “default” path and “default” program are. Something like that may lead us to a point where we could decorate a manifest such that we know the installer doesn’t add the path, so we could inform the user that it’s something they could/should do. Changing environment variables will still require a shell restart or a reload environment variables to actually function. That’s likely something we would still want a user to actively do so we don’t inadvertently break something else running on the system “at the same time”.
This isn’t an exact duplicate, because opening a new shell doesn’t change the behavior. the Application is still not in the PATH.
I wasn’t being dismissive. Fan is literally a shortened form of the word fanatic. Someone who is fanatical about something is, by the very definition of the word, not going to be that logical in their decisions.
Btw, on latest versions of Windows, Terminal should already be the default, with the legacy individual terminals being moved to a holdover legacy option
Fanatics don’t need an excuse to trash on Windows. That’s kind of part of being a fanatic lol
Sure, it would be nice. But it really doesn’t affect me after 30 years of using Windows and nothaving it. 😃 I have never used it and frankly, a new shell is also useful for other reasons. SOME packages update the
$Profile
, so the best way of using the new app is to restart Psh. I get that a few users want something better (and sure it would be nice) but it probably won;t h appen.If you really want this feature, then first show how winget can affect the $Path variable within the PowerShell process. Maybe I am missing something but I can’t see how it could be done. I am pretty sure the Winget process spawned from PowerShell can not affect the calling process (i.e. PowerShell).
I suspect PowerShell could have an API added to enable this, but it would be a wide-open security risk. And messy - do you really want $Profile to be re-executed.
I am having difficult understanding why needing to restart a shell after running an installation tool that updates the system path. This, to my memory, has never been the case with Windows. Somehow, saying this is a huge major catastrophic deal breaker seems a tad over the top! 😉 I have seen zero evidence that this is actually any soft of major issue although I could be looking in the wrong place.
I am not even sure how winget could do this.at least for PowerShel - and if it could, it would certainly be a security risk. Can you suggest how this could be done? Because I can not see any way that is both NOT a hack and NOT a security risk.
My suggestion if this the team close this issue as either Won’t’ Implement or By Design.
I can’t think of any another package manager that fails to do this, so yes it’s very unexpected behavior, so yes it’s alpha.
It’s an alpha just because it doesnt do something that most programs also don’t do? Outside of choco and scoop, I’m not sure people realize just how rare it is to find a program that supports regenerating the environment block after process creation.
The current behavior is not customer friendly since it doesn’t even show a warning about this issue, I would recommend as a stop-gap to add a yellow warning with the description of the current behavior (which is not to set the PATH) and describe in detail what are the manual steps that must be taken to overcome this pain
@jazzdelightsme,
That’s an interesting idea. It’s something we could experiment with.
The real challenge is the App Execution Alias for winget might get resolved before the .ps1. If we’re running a PowerShell cmdlet we might be able to do that more cleanly than in the CMD.exe shell.
Also, FWIW, https://github.com/microsoft/terminal/issues/15102 is not the solution to this issue. That’s tracking a perf improvement to the way that Terminal reloads env variables in 1.18+. In 1.18, the Terminal will reload environment variables when making a new tab (so you’ll no longer need to quit out of the Terminal and restart). You’ll be able to just open a new tab (or restart the connection).
But ultimately, there’s no way for the Terminal to force a shell (cmd, pwsh) to update its own environment variables.
@zeratax That is related to https://github.com/microsoft/winget-cli/issues/2909 and the fix for it was merged in https://github.com/microsoft/winget-cli/pull/3002. The fix will likely appear in the next release for WinGet.
What happened to @yigitemres’s idea? This is where everyone is correct but too far into the infrastructural weeds.
Some simple interface emitting to the effect of “winget could not confirm an installation or path location and it’s possible the installer cannot either, here are some options and info, ie run THIS COMMAND and restart your terminal”
I heard @denelon talk about how a design goal was to make it easy and inviting for package maintainers - how about the same courtesy for users of the tool? and by users, I mean at the API level. I think we are okay with some flag argument configuration, but this seems like an easy win.
I think it’s hilarious there’s comments about “MS is different than linux”, lol then why make the tool at all? it’s clearly a clone of Apt/etc (which is a good thing!).
I’m honestly surprised winget bothers supporting non-portable apps. Why is that? I would not expect winget to support
msi
installers, yet it does. This is surprising. If I wanted to install something with anmsi
installer, I would expect that I would have to run it manually. I wouldn’t want winget to run an installer like that for me.If closing and reopening the shell worked that would be an outstanding improvement over the present situation . I can understand that these are difficult compromises, but if avoiding them means a completely broken experience, then I’d say your definition of “absolutely necessary” needs to be reevaluated. Scoop currently works, so I’d strongly disagree with your characterization of this as “the very same issue”. This will unambiguously kill winget in the long term if this issue is not fixed. We all want winget to succeed, and we should not put our heads in the sand and pretend there aren’t currently working solutions to this. We may not want to choose the existing solution, that’s fine, but this project is broadly doomed without a solution. It’s not great that windows is decades behind the competition in automation, and this is even more extreme for windows server where the need is even more important.
This is after I closed and reopened powershell. At the very least allow me to run the winget installed programs by doing
winget run program
, while I would be very unhappy with that as a solution it would at least allow it to be possible to use the things I’ve installed.Yes, today, WinGet uses the “known” installer types like inno, nullsoft, wix etc. as hints to determine things like installer switches for silent or “silent with progress” (our default mode). We also support switches for those modes when they are unique (this is very common with traditional .exe-based installers). They may also help with knowing how to do a “user” vs. a “machine wide” install.
For Git,
winget install git.git --silent
orwinget install git.git -h
should perform a silent installation without any output.One of our critical goals early on was to meet developers (packages) where they are, and not to require them to be rewritten or to have to completely rewrite their installers. That does lead to challenges when the installer doesn’t have parity in “silent” with what is supported via “interactive”.
I see this as a bit of a “chicken and egg” challenge. We need a package manager as a bit of a forcing function to establish best practices. As you are stating, if the packages aren’t ever “fixed”, or the package manager can’t reason about them, then it’s a bad experience. We have taken the approach to assert rational “default” behaviors, and then extend with settings and arguments so the desired outcomes can be achieved. Today we have “–override” which allows overriding arguments WinGet defaults to with the manifest/installer type so users can specify the arguments they want. We also have an ask for an “augment” type of behavior so we can preserve the default switches and simply “add” to them.
@denelon I’m going to talk a little bit about git, as a way of talking about strategy with installers. Git appears to have silent/unattended installation flags. https://github.com/git-for-windows/git/wiki/Silent-or-Unattended-Installation Does winget currently support the ability to use those? Or we could use the portable similar to how scoop does https://github.com/ScoopInstaller/Main/blob/master/bucket/git.json . It feels like critical packages have been broken for months or years, and that’s really very bad for winget. If there’s an incorrect way to do something, people will do it. If software that people rely on is provided in non-working condition, it will erode and eventually destroy winget. Nothing is more important than trust with a package manager.
I still have not “bought-in” to trusting winget, but the value it could provide if I can use it to quickly script installations on a developer’s machine or server is incredibly obvious. If anyone doubts it, tell them to try Fedora or any other major Linux distro for a day where any software from any provider is available with ease. I can add external repositories from microsoft, dell, or anyone I want, as well as using a well curated list of packages that are certain to work well. It’s something that I miss a lot every time I go to a windows server or my work computer.
While that would surely work and the flow could be reduced to a PowerShell snippet I’m not sure about the manageability of adding hundreds of packages to the path (my workstation has a bit more than 110 packages, although not all should be in the global path). I should note that chocolatey, which I used previously, creates a «shim» exe in a global directory that is added once to the path.
That approach seemed to work well for me.
workaround: After installing vim.vim with winget, the quick way to add it to path: right click start button, select run run the following command: systempropertiesadvanced go to Environment variables, select Path [Edit…] [New] C:\Program Files (x86)\Vim\vim82\
Since the vim version number is used in the directory name, you might have to find the location of newer vim versions by searching for it in the start menu: right click ‘open file location’ and adjust the path accordingly
restart the command prompt/windows terminal for it to take effect
but… will it? 😄
https://github.com/microsoft/winget-cli/issues/4008
This is awesome!! thanks @jazzdelightsme for your hard work and thank you @denelon for supporting this. Very exciting 😃
@denelon Is there any movement or interest in this issue?
I am still waiting for a good explanation as to how this could work. How could Winget re-build $Pasth through running winget? While asking for any feature is great - understanding how and if it could be implemented is equally as important. I’d be grateful if those advocating this feature could explain how it could be implemented just within Winget.
Can we please not be dismissive? Many people who are fans of linux also are fans of windows. It is not the year 2000, people are allowed to like more than one thing. In fact I’d argue pushing for improvements is more of a sign of being a fan than moping about how something isn’t possible to fix (not to say that you’ve been doing that). I wouldn’t have said anything if this weren’t a serious UX issue, I’m not cruel. I do like linux, but I also care about Microsoft continuing to exist. We’re all poorer with fewer options in the market. Right now I think the package manager is one of the largest advantages linux has over windows server and I think this glaring UX issue makes winget look broken to anyone trying it out. It’s depressing to me that Microsoft isn’t putting more resources into this and makes me afraid that in the future we’re going to have a duopoly of IBM and Canonical for server operating systems with support.
For what its worth, there IS actually progress being made to help out with that, even though it might seem otherwise. If they are using Windows Terminal, you don’t have to close the whole terminal, just open a new tab
I fully agree with @safakgur and I’m not trying to argue winget is useless. I probably got a little polemic when I felt people were arguing against the feature entirely. At the same time, I really want to tell people “Just use winget”. I hear back “It didn’t work” and then I say “Oh just close and reopen the window” and then they don’t understand why there’s this constraint I have to explain the current state of things. It would be very nice if I could just say “Just use winget” and that’s the end of the conversation. When I lead with “Just use winget, and make sure to close the terminal entirely after running it” they think other things are wrong with it and they don’t try it. If I explain after they hit the snag it feels dishonest, though it does get slightly better traction. I think this feature is undervalued in terms of how it affects adoption, especially from a mac & linux users that are used to having a package manager and would already appreciate it. Apologies if I have come across as dismissive of the project as a whole, that was never my intent.
Lock environment block regeneration behind UAC. That way, if you want it, you need perms. If you have a UAC bypass circumstance, you have worse issues to deal with than just being able to call from an open terminal or not
Well that’s what happens when I try to share it with anyone, so I don’t. I’m not here in the comments because I don’t like the project, I’m here because I like it but I can’t actually share it because anyone I share it I’d have to explain around the very first step of using it. It’s not a dealbreaker for me using it, but it is definitely a dealbreaker for sharing it with others.
I really do not understand the real issue. If you run any installer from the command line/powershell, I never assume the path will get updated (in the current session). When the installer finishes, I open up a new shell and move on. I wonder how much workflow is predicated on that approach. For me, Widget’s behaviour is consistent and expected., After installation completes, one just opens a new shell. and everything works as it should. For me, Windows has always worked this way - or is my memory faulty?
So far as PowerShell is concerned, I am unsure how Winget could force an update to the path variable (
$Path
) within the current PowerShell session. As an aside, providing such a general mechanism within PowerShell also might be a security risk.I understand that this product is doing cool new things, and I think that’s great. I also understand that an app that breaks the user flow entirely is not ready for beta. People would attempt to use it, say it doesn’t work, and then not use it again. Software that can’t be used without a testing script is in alpha, even if it is for usability reasons.
Our preference for integration is to call the COM API rather than winget.exe. In the case of PowerShell users, I think we could just make that work as we would like, but we’ll have to continue investigating.
We do have plenty of cases where the MSIX behavior isn’t what customers want, and they are sensitive to changes in the name of the “primary” executable. If this does actually end up being the right thing to do to resolve the challenges associated with path, it might be OK though.
Several users have automated solutions calling winget.exe directly in the path where the files get laid down rather than using the App Execution Alias that typically catches “winget” via Windows Terminal, PowerShell, or what ever shell they happen to be using.
Not a bad idea, I see how that would get pretty confusing. I get confused enough just having multiple types of processor in the same window lol
Sadly, no. There is a distinction between the shell used to communicate with the kernel and the terminal used for rendering input/output. The winget.exe cli is being called in a process, and it doesn’t have a reliable way to look up and see what called it. There are special cases that allow us to know when the PowerShell cmdlets are being invoked by virtue of the code being in a PowerShell module so that may be one area where we can relatively easily enlighten ourselves.
Ugh, I was thinking of resolution preference between e.g.
.ps1
and.cmd
(where.ps1
would win), but you’re right that it would be a problem for.exe
versus.ps1
; my bad.But having a
winget
command exported from a PowerShell module would take preference. It would have to be a “simple function” (as opposed to an “advanced function”) so as to be able to function as a completely transparent stand-in for thewinget.exe
command.However I think it is still worth considering dealing with
%PATH%
order, in order to also provide a similar.cmd
solution forcmd.exe
users. I.e. if we putwinget.ps1
andwinget.cmd
files intoC:\windows\system32
, they should be ahead of the windowsapps alias EXEs on the PATH; and then if a user just says “winget” (instead of “winget.exe”) then the right thing would magically happen in either shell. (Nobody likes putting more stuff into system32, but I think it is justified in this case.)@voronoipotato :
Even supposing that were possible (you would have to do that to a different process (the shell process)), you would be surprised how much stuff that would break: there are many systems out there that depend on environment customization from the parent process (so reading fresh values straight from the registry would wipe those out).
So what you would have to do is compute a diff: read the Machine and User values straight from the registry, do the install, read the values from the registry again, and compute the diff (and assume that if anything else was messing with the registry values concurrently, “it’s fiiiine”). But then you still have the problem of adding the new stuff to the correct shell process.
However, your posting of PS script gives me an idea of a hack/workaround that may be both “good enough”, and not so hacky/gross as to disqualify it as a legit step forward:
What if
winget.exe
also shipped with awinget.ps1
file next to it? When in powershell, if a user were to runwinget
, they by default would get the.ps1
before the.exe
… so then the.ps1
could handle doing the path diff’ing and apply it in-process… @denelon, what do you think of that?The critical timing for the symbolic link creation is when you install the package. Once it’s installed, it should either be in the path with the symbolic links, or as a path entry in the environment variable. Unfortunately, a new terminal Window isn’t sufficient to get the environment. The entire Windows Terminal needs to be restarted if you’re using Windows Terminal.
Do you have developer mode enabled on your machine? Did you install via administrator or user (Terminal, PowerShell, CMD.exe).
If it appears in your user environment path, it most likely means you didn’t have developer mode enabled or use an administrator shell.
I was going to test, but I get two results. Which did you install?
On the contrary! I think it’s quite nice that multiple installer types are supported because that way I can actually use winget to install nearly everything and even provide invocation flags for the installers to fully automate them. See for example here what I mean.
@denelon Ah, I closed the individual tab of windows terminal without closing the whole program. Very strange behavior but that worked, thank you. I had expected that each tab ran independently. I wonder how many other people here ran into the same snag.
@voronoipotato I’m not familiar with neovim. If you download and “run” the installer, does it add itself to the path? I’ve seen a couple of cases where the “interactive” installer has an option to add the directory to the path, but when run “silently” it doesn’t. I’m not sure if that’s the case here or not. If it’s just a switch that needs to be passed, the manifest can be updated to include that switch for “silent” and “silent with progress” variations of install.
I just ran
winget install neovim
in Windows Terminal (PowerShell) in user mode. I agreed to the UAC prompt. After it succeeded I closed and reopened Windows Terminal, and it appears to have worked.I assume you are comparing the Windows Package Manager against Linux package managers. There are some very subtle differences between Linux and Windows. The Windows registry and the various “public” and “private” APIs add a bunch of complexity (read constraints). There is a long history of building an “installer” for Windows whether it’s a custom .exe-based installer, or MSI, and more recently MSIX. These are of various different quality. They also generate several different “classes” of behavior that we need to be able to reason about.
Given an arbitrary installer, there could be any number of behaviors it supports (or not). Some installers don’t add the executable location to the path, and WinGet doesn’t “know” this information beforehand. We also don’t want to go down a path where we’re writing branching logic for each version of any available package. That has led us to building a more robust manifest to deal with many of these variations.
We’ve been discussing the notion of refreshing the path (or any other environment variables) after install or upgrade, but we don’t necessarily know which shell we’re being executed in to know which variables to refresh. There are differences between cmd.exe and PowerShell so there is no “one size fits all” solution there. There are other shells that handle things differently so we wouldn’t know what to do for them either. Even if we were to add a prompt to “refresh the path”, it might not apply in all cases.
Best practices include building a better installer (which isn’t viable in the short term for many organizations) and testing the experiences with WinGet. Different packages (publishers) make different assumptions about their users, so the advent of Windows having a package manager is still “new”.
I know right. 😦
Sent via Superhuman iOS ( @.*** )
I just tried installing a package with winget. It was relatively easy to use
winget search
to find the package andwinget install package
similarly “just worked”.Then I got very sad when apparently it didn’t “just work” and my package was seemingly not installed. It’s not on the path, and since I have no idea where it got installed, it may as well just not have been installed at all.
This makes winget pretty much useless. Please prioritize this issue ASAP. Until this is fixed, I don’t see any value in winget.
If there are arguments that set the path correctly, then yes, they could be added to the manifest. It may still require a restart of the shell or the environment variables to make it available. You can test locally with “-m <path to manifest>”. In some cases, those arguments haven’t worked when the install location was modified by the user.
It’s not a issue with WinGet, that’s how PowerShell is handled even if you manually use the installer. They are installed as separate programs because the version from GitHub can’t replace the system version without being handled in special ways. Having it as a separate program allows for faster upgrades and other things that would normally have to be locked behind the normal update cadence
Hello @denelon , trying to give winget a second chance. I thought well maybe it’s not really for terminal programs. I hit a similar (less impactful) issue again today where I followed the guide at https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.3 where I ran
winget install --id Microsoft.Powershell --source winget
and it installed… but initially I couldn’t find it at all. I was able to find it by searching for powershell, as “powershell 7”.I’m not used to new versions installing as separate programs. Typically when I install a program it actually replaces the older version unless otherwise specified. If I use winget to provision machines, people are going to run the old old version of powershell that is still there because the old version comes up first in the search. When I call the powershell command, it still calls the old powershell. It feels like the team isn’t dogfooding winget to provision their machines, because this tool is missing very simple and very critical comforts.
Normally I would make a new issue for something like this, but I’m afraid you would prioritize it over fixing the paths issue, and if that’s the case I don’t want this fixed. I would pay a fair bit of money to stop all other issues until this issue is fixed since it severely limits the default windows experience especially compared to the competition.
Is there any due diligence performed on the items in the winget repos? Does Microsoft do any validation of applications??
Yes I understand But wiget-cli should not accept such packages in repo if they don’t add themselves to path.
Makes sense-- it does not appear to be a problem with winget, but with the vim package; I guess the question then becomes how should winget handle packages that don’t add themselves to PATH? Is this exclusive to the vim package, or have other packages shown this behavior too?
I’ve been working on the backlog recently. You can take a look at the milestones to see what we’re planning.
We do plan on having the ability to add the path for .zip, .exe, and standalone/portable apps. I’m not sure what we’d be able to do with an installer that doesn’t provide a path. If we specify a path during “install” time for packages like this, we might be able to add that path to the environment. Is that what you would be looking for here?
I think that linux users benefits WSL as a package manager when native gui server comes with it. I use WSLGentoo and when gui server comes with it, I will migrate fully and only use
winget
in order to contribute it.