Windows PowerShell correctly inherits environment variables from the environment -- although it may add paths to these variables, it doesn't ignore the existing environment.
PowerShell Core sets the PSModulePath -- completely ignoring and overwriting the existing environment, including the default values set in the Windows System Properties control panel...
This makes PowerShell Core's PSModulepath basically impossible to manage, since it can only be set reliably in a machine profile script --which depend on the _install location_ of the shell, which changes with each release!!
From Windows PowerShell run:
$Env:PSModulePath
pwsh -noprofile -command { $Env:PSModulePath }
pwsh -noprofile -command { powershell -noprofile -command { $Env:PSModulePath } }
From pwsh
run:
$Env:PSModulePath
PowerShell -noprofile -command { $Env:PSModulePath }
pwsh should respect it's environment.
pwsh overwrites it's environment
> $PSVersionTable
Name Value
---- -----
PSVersion 6.0.2
PSEdition Core
GitCommitId v6.0.2
OS Microsoft Windows 10.0.17134
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
There's explicit code clearing the variable
yes, but that code is based on the incorrect (or rather, outdated) assumptions that "The machine-wide and user-wide environment variables are only meaningful for full ps"
First of all, since PowerShell itself does not set those environment variables, there is no basis for this assumption. These are environment variables under the control of the user. You have no right to ignore them.
Second, as noted on #2636, many of the core modules _do_ work. You've even released a module predicated on the fact that this is, in fact, not true 馃槈
We can't on the one hand claim that many (or most) modules will just work, and on the other hand say that the environment variable is _so toxic_ that we can't trust users (and enterprises) to deal with it properly. Especially since this breaks all _reasonable_ expectations regarding environment variables.
Maybe we should have another environment variable $ENV:PSModulePathCore
. On startup, if PowerShell Core sees this variable, it uses it otherwise it falls back to $ENV:PSModulePath
. With two variables, then powershell
can call pwsh
and pwsh
can call powershell
and everything works. And eventually we can create a PowerShellCommon
module directory for modules that work with both and that both variables include.
A separate $Env:PSCoreModulePath
environment variable kind-of makes sense.
However, there are probably a lot of scripts and modules using $Env:PSModulePath
... I mean, at a minimum, people's profiles, and modules like PSDepend. Would you just read it and overwrite $Env:PSModulePath
? Would that help?
Could we rely on the modules themselves setting CompatiblePSEditions
, and let each version of PowerShell ignore modules that aren't compatible? (Actually, sure this wouldn't work, nevermind. Most of the modules that I'm concerned with are legacy modules which aren't going to be updated with CompatiblePSEdition
any time soon, but which still work ... )
Bear in mind that in the _near future_, the more frustrating problem is _Windows PowerShell_. As new modules come out which take advantage of PowerShell Core functionality, Windows PowerShell won't be able to use them, and it _does_ inherit the environment variable, already.
I mean, at a minimum, people's profiles
There are different profiles for desktop and core. You have to expend effort to get them to share common code and work properly. (e.g. no loading winform
assemblies in your Core profile). So you put edition-specific tweaks in the appropriate profile.
However, there are probably a lot of scripts and modules using $Env:PSModulePath
Most scripts and modules depend on the module path being set correctly for the PS edition they are using. With separate variables, by default they will only load modules from the module directories associated with their shell edition. For things that work directly with PSModulePath, they'll have to be updated to understand PowerShell Core.
Could we rely on the modules themselves setting CompatiblePSEditions, and let each version of PowerShell ignore modules that aren't compatible?
Without separate 'edition' directories, how do I have both "core" and "desktop" install paths for a given module/version? (Nuget does this with <package>/<version>/lib/<editionEquivalent>
but that would require changing both Core and Windows Powershell so it is unlikely to happen.)
Bear in mind that in the near future, the more frustrating problem is Windows PowerShell. As new modules come out which take advantage of PowerShell Core functionality, Windows PowerShell won't be able to use them, and it does inherit the environment variable, already.
All the more reason to have separate module paths. I should be able to do
powershell {
Get-ADComputer ...
}
from pwsh.exe
and it should just work.
Most helpful comment