-
Notifications
You must be signed in to change notification settings - Fork 130
Version Specific $ENV:PSModulePath Variables #133
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
Conversation
From: PowerShell/PowerShell#7324 |
If we stay with env var, I noticed another issue that would not be resolved by having $env:PSModulePath6. I was testing a private build of PSCore6 from PSCore6.1. Because the child pwsh inherited the 6.1 paths, those modules are imported first and complain that they can't load because they require 6.1. We could add some code to avoid this, but that seems more like a patch than a solution. Perhaps we should just move away from $env:PSModulePath altogether and require modules to just be in the 3 locations (shared, user, and $PSHOME). The actual paths can be in the configuration json file. |
@SteveL-MSFT moving away from the env var may be problematic if there is no way to modify the module paths in-process. Several of my work flows for module dev involve pre-prending the curren PSModulePath with the location of the build output. I also use this to allow a folder to serve as an alternate to the 3 paths in pipelines. IMO, this doesn't need to be an env var, but it does need to retain the ability to add paths in-process. |
@markekraus Do you mean that you redirect |
@iSazonov No. I mean that I regularly prepend paths to PSModulePath. For example, In-pipeline I will add It would be painful to be forced to install the modules every time, or to be forced to import the modules via full path just because PSModules path is now restricted to 3 locations. This kind of functionality needs to be preserved, but, it doesn't have to be a env var. so long as the existing paths can be inspected and modified. For example, it could be a cmdlet. |
@markekraus Thanks! My suggestion is only hard-code paths to standard modules (Microsoft.PowerShell.Diagnostics Microsoft.PowerShell.Host, Microsoft.PowerShell.Management, Microsoft.PowerShell.Security, Microsoft.PowerShell.Utility ) and always load them from |
@iSazonov I'm indifferent to that. My only concern is what @SteveL-MSFT said:
I don't care how or where the original paths are set for the current process. pwsh 6.0.0 broke the usefulness of the env var anyway as it doesn't get passed to child pwsh processes such as jobs or calling pwsh.exe. But I do care that we should be able to change these paths (add, remove, replace) in-process somehow. If the paths are no longer in an ENV VAR, than we need some cmdlets to manage the paths. Or if it's now managed as a magic variable.. or whatever. Just so long as we are not locked down to only the paths that are arbitrarily decided before my code is running. |
We could consider limiting the paths as security option for closed environments. |
I wish there was at least one place on the default lists where compatible modules could be installed. Right now we're all juggling, copying, updating and making a proper mess of things just trying to keep our modules up to date in both shells, and it's very frustrating. I've never really liked the idea of having multiple path variables -- modules were supposed to work and separate paths just means that I'll have to modify my shared profile to update both/all of them to include my development folders. However, the fact that PowerShell 6 doesn't properly inherit the "environment" variable is a really bad bug, and ... I'll happily accept this as a work aroundIt's pretty clear that most people (and production servers) are going to use either PowerShell 5 or PowerShell 6 and not a mix, and just need each of them to work. They don't have my problems, but they do have a problem with the non-environmental nature of the current PowerShell 6 PSModulePath. P.S. I thought there already was code protecting core modules from being loaded from elsewhere? |
Absolutely not @iSazonov The only reason why PSModulePath exists is as a convenience, just like every other PATH environment variable. You can't lock it down for security because it's emphatically not a security risk in the first place. We have tools for preventing attackers from running malicious code. Making it harder for people to find things is not one of them. P.S. Please note that Import-Module not only accepts direct paths, it doesn't even need anything on disk at all (see New-Module). |
@markekraus - you can change PSModulePath in process (at least on windows) with [System.Environment]::SetEnvironmentVariable('PSModulePath','C:\Code\;'+$env:PSModulePath,'Process') not tested this off windows though but this does work on 6.1.0-preview3 on win10 Edit confirmed this works on Ubuntu with 6.0.3 as per above |
I just re-read the previous comments, and I have to say (for what it's worth) that I think the PSModulePath6 really needs to be an Environment path variable as proposed in this change. Please let's not consider changing it into something other than an Environment variable, or altering it on load (with the possible exception of appending paths), or changing command or module precedence to ignore the PSModulePath -- these things were tried before and did not turn out well (I can forward email threads from 2014 when a change "to prefer PowerShell’s built-in modules" was made "for both security and reliability reasons" the last time, if we don't remember this). The computing community have been managing available applications/commands (and libraries) via environment path variables for decades (and working around minor gotchas with inheritance). If you simply make this an environment variable that inherits properly, every single one of these other problems are easily worked around in profile scripts which we all know how to write and are problems which computer users have been dealing with successfully for a very long time. P.S. @kilasuit I think Mark's trying to say it needs to be changeable, in response to Steve's comment suggesting it could be hard-coded instead of an environment variable. |
@kilasuit What @Jaykul suggested I meant is correct. I'm aware it can be changed in-process now (I do this often), but what @SteveL-MSFT proposed appears to make that impossible once implemented. |
@markekraus the developer scenario is one we want to support. Having application installers extend PSModulePath, however, was always a bad practice. I would certainly support cmdlets to manage the "path" even we decide to go the non-env-var route. However, even with the env-var route, the current proposal, as written, has the problem of starting different versions of PowerShell from PowerShell which is not common, but not rare either. |
Agnostic of implementation (this may be impossible), we think there's three scenarios that need to addressed here:
In the first case, we think that it's less likely that PS Core modules will work in Windows PowerShell. People will be calling it for legacy behavior, and they will wants Windows PowerShell to start as it does when created from a fresh process. To that end, if it's in the registry, we should replace what is passed by the parent In the second case, you may very well want both Windows PS and PS Core modules to run. Given our lean towards attempting backwards compatibility (especially as we move into .NET Core 3.0), we should join the inherited PSModulePath with the default PS Core paths (Users, Program Files, and system32). In the last case, we think that users operating in a purely PS Core world should do the right thing and modify their manifests and use In any case, we will not create a new environment variable, as it's a sweeping change to the existing module semantic that can ultimately be avoided with well-documented asymmetry. |
@joeyaiello Could you please clarify? Everyone above agreed that we have to have env:PSModulePath6 to address all these three scenarios. Also you forget about side-by-side pwsh-s of different versions scenario. |
Had more discussion on this with @JamesWTruher and @HemantMahawar today. A few notes:
The scenario I'm trying to solve for is this: This will expose potentially incompatible modules to PowerShell Core, but our goal is to continue maximizing back compat in a post-.NET Core 3.0 world, and we don't want to make IT administrators opt in to a world by pushing new policy that is specific to something like Additionally, the pain of incompatible modules has been our single most powerful lever for updating module compatibility, so surfacing more modules in PS Core will help us increase compat. More succinctly than I stated above:
|
Side-by-Side scenarios we need consider:
Initial problem in #7324 was: Import-Module Microsoft.PowerShell.Utility
Import-Module : The version of Windows PowerShell on this computer is '5.1.18200.1000'. The module 'C:\program
files\powershell\6-preview\Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1' requires a minimum Windows PowerShell version of '6.1' to run. Verify that you have the minimum
required version of Windows PowerShell installed, and then try again. That is - Windows PowerShell uses PSModulePath to discover modules and pwsh path is on first place. But we haven't on first place path to pwsh and Windows PowerShell at the same time. So we can resolve this only having:
|
@PowerShell/powershell-committee discussed this further. Current proposal is:
This should solve the scenario where PSCore6 starting powershell.exe will have powershell.exe not inherit incompatible $env:PSModulePath and for PSCore6 started from powershell.exe to have the complete path. |
It seems this address nothing from my previous comment. If we take the search list from the config file, then why do we need to change For every pwsh process the search list should be recreated as $PSHOME/Modules+paths from +config.json+$env:PSModulePath |
Would you mind rephrasing your concern? We're having a bit of difficulty parsing your feedback. In particular, it seems like you're primarily concerned about Windows PowerShell being started in PowerShell Core here:
But then this sounds like a concern about the other direction:
Unless it's possible that you think we're permanently creating or overwriting an environment variable here?:
That one will just be created in process, so that users can use the existing mechanisms for editing it in a runspace, and so subsequent pwsh instances created in that pwsh inherit it properly like shells are supposed to. |
Sorry my feedback was confusing. My feedback was that "all is bad". :-)
|
I feel like you're over-engineering this, and worse, that you're doing so because you think your users are not smart enough to manage it on their own. Really, it's pretty simple:
Conclusion: users can handle this on their own, as long as you stop breaking it. Forcing your modules to the front is unnecessary, and breaks things for developers who configure their development paths in priority. You should only add your own paths if they're not already in the list at all. Putting environment variables in config.json is confusing, obscure, and unecessary. If you want to do special environment stuff for Remember that Daniel Webster quote?
If you still feel that something must be done, I'd suggest:
|
Environment variables are not always as simple as they seem. I'd argue that we're doing here is more akin to The original point of this RFC was around the Windows PowerShell <--> PowerShell Core inheritance problem. I think we all agree that Windows PowerShell shouldn't be modified, but there's some tactical stuff we might be able to hack in to solve that problem. Now, though, the scope has expanded in this conversation to talk about managing the environment variables on non-Windows platforms. And our discussion has turned to the login shell inheritance issue discussed in:
Whatever we do here should be rationalized with our handling of PATH as well. @SteveL-MSFT is going to open an RFC on that behavior, and we might need to rewrite this one to stay in lockstep with PATH. |
Since MSFT team was announce PowerShell 7.0 as big step to replacement of Windows PowerShell the RFC may lose relevance at all. |
@iSazonov I agree that PS7 makes this somewhat irrelevant, however, we still have an issue with starting PS7 from WinPS and vice-versa. The solution might be to simply special case just those use cases. |
@SteveL-MSFT I re-read the issue PowerShell/PowerShell#6850 and the RFC and think that we can change PS7 to inherit PSModulePath and share it with WinPS if we force to load modules only with CompatiblePSEditions in manifest (or force to use "-Force"). We could add option to preserve old behavior if this is needed in some scenarios. If we announce this now module owners will have time to update their modules. |
@PowerShell/powershell-committee reviewed this again. We've made a small edit to the proposal here which is what we are approving for PS7. |
Will it be fixed in new RFC? |
Initial draft of "Version-Specific $ENV:PSModulePath Variables" RFC.