-
Notifications
You must be signed in to change notification settings - Fork 130
Draft of PSModulePath behavior in PS7 #233
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
Merged
Merged
Changes from 5 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
c60b761
Draft of PSModulePath behavior in PS7
SteveL-MSFT 9306f44
clarify PS7 current behavior
SteveL-MSFT 62a15fd
remove unncessary steps in constructing WinPS PSModulePath
SteveL-MSFT be58acf
clarify `Windows` module path on PS7 startup
SteveL-MSFT 80635df
Update adding more details.
SteveL-MSFT 009c4a9
Prep RFC0049 (PSModulePath with WinPS/PSCore) for merge
joeyaiello File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
--- | ||
RFC: | ||
Author: Steve Lee | ||
Status: Draft | ||
SupercededBy: n/a | ||
Version: 1.0 | ||
Area: Engine | ||
Comments Due: 11/30 | ||
Plan to implement: Yes | ||
--- | ||
|
||
# PSModulePath When Starting PowerShell within PowerShell | ||
|
||
When starting PowerShell from a different version of PowerShell, the PSModulePath | ||
should reflect the module search path and only include segments appropriate for | ||
the version of PowerShell being started. | ||
|
||
## Motivation | ||
|
||
As a PowerShell User, | ||
I can start a different version of PowerShell within PowerShell, | ||
so that I can do things required by that specific version of PowerShell. | ||
|
||
## User Experience | ||
|
||
### Starting Windows PowerShell from PowerShell 7 | ||
|
||
```powershell | ||
PS7> $env:PSModulePath.split(';') | ||
C:\Users\user\Documents\PowerShell\Modules | ||
C:\Program Files\PowerShell\Modules | ||
c:\program files\powershell\7-preview\Modules | ||
C:\Program Files\WindowsPowerShell\Modules | ||
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules | ||
|
||
PS7> powershell -noprofile | ||
WinPS> $env:PSModulePath.split(';') | ||
C:\Users\user\Documents\WindowsPowerShell\Modules | ||
C:\Program Files\WindowsPowerShell\Modules | ||
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules | ||
``` | ||
|
||
### Starting Windows PowerShell from PowerShell 7 with additions by user | ||
|
||
Here a custom `C:\MyModules` is added | ||
|
||
```powershell | ||
PS7> $env:PSModulePath.split(';') | ||
C:\Users\user\Documents\PowerShell\Modules | ||
C:\Program Files\PowerShell\Modules | ||
c:\program files\powershell\7-preview\Modules | ||
C:\Program Files\WindowsPowerShell\Modules | ||
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules | ||
C:\MyModules | ||
|
||
PS7> powershell -noprofile | ||
WinPS> $env:PSModulePath.split(';') | ||
C:\Program Files\WindowsPowerShell\Modules | ||
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules | ||
C:\MyModules | ||
``` | ||
|
||
### Starting Windows PowerShell from PowerShell 7 with deletions by user | ||
|
||
Here the `System32` path is removed | ||
|
||
```powershell | ||
PS7> $env:PSModulePath.split(';') | ||
C:\Users\user\Documents\PowerShell\Modules | ||
C:\Program Files\PowerShell\Modules | ||
c:\program files\powershell\7-preview\Modules | ||
C:\Program Files\WindowsPowerShell\Modules | ||
|
||
PS7> powershell -noprofile | ||
WinPS> $env:PSModulePath.split(';') | ||
C:\Program Files\WindowsPowerShell\Modules | ||
``` | ||
|
||
### Starting Windows PowerShell from PowerShell 7 with additions and deletions by user | ||
|
||
Here the `System32` path is removed and the `C:\MyModules` path is added | ||
|
||
```powershell | ||
PS7> $env:PSModulePath.split(';') | ||
C:\Users\user\Documents\PowerShell\Modules | ||
C:\Program Files\PowerShell\Modules | ||
c:\program files\powershell\7-preview\Modules | ||
C:\Program Files\WindowsPowerShell\Modules | ||
C:\MyModules | ||
|
||
PS7> powershell -noprofile | ||
WinPS> $env:PSModulePath.split(';') | ||
C:\Program Files\WindowsPowerShell\Modules | ||
C:\MyModules | ||
``` | ||
|
||
## Specification | ||
SteveL-MSFT marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
By default, PowerShell starts with (in order): | ||
|
||
| Segment Description | Windows PowerShell example | PowerShell 7 example | | ||
|---------------------|--------------------------------------------------------------------------|---------------------------------------------------| | ||
| User modules | C:\Users\user\Documents\WindowsPowerShell\Modules | C:\Users\user\Documents\PowerShell\Modules | | ||
| System modules | C:\Program Files\WindowsPowerShell\Modules | C:\Program Files\PowerShell\Modules | | ||
| $PSHOME modules | C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules | c:\program files\powershell\7-preview\Modules | | ||
| Windows modules | | C:\WINDOWS\system32\WindowsPowerShell\v1.0\Module | | ||
| App added modules | C:\Program Files (x86)\Microsoft Azure Information Protection\Powershell | | | ||
|
||
Currently, applications (or user) adding additional paths to `$env:PSModulePath` are dropped in PowerShell 7. | ||
|
||
### Windows PowerShell PSModulePath construction | ||
|
||
Windows PowerShell has logic at startup to construct the PSModulePath based on (simplified version): | ||
|
||
- If PSModulePath doesn't exist: Combine `User` modules path, `System` modules path, and `$PSHOME` modules path | ||
- If PSModulePath does exist: | ||
- If PSModulePath contains `$PSHOME` modules path: | ||
- `System` modules path is inserted before `$PSHOME` modules path if it's not there | ||
- else: | ||
- Just use `$env:PSModulePath` as-is as user had deliberately removed `$PSHOME` | ||
|
||
`User` module path is prefixed only if User scope `$env:PSModulePath` doesn't exist. | ||
Otherwise, it is assumed the user removed it if it's not there already. | ||
|
||
There are no changes planned for Windows PowerShell 5.1, so this existing logic is in place. | ||
|
||
### PowerShell 7 startup | ||
|
||
Currently, PSCore6 doesn't use contents of `$env:PSModulePath` if it detects it was started from PowerShell | ||
and simply overwrites it with `User` modules path + `System` modules path + `$PSHOME` modules path + `Windows` modules path. | ||
|
||
Intent is to have `PSModulePath` behave how `Path` env var works on Windows. | ||
`Path` on Windows is treated differently from other env vars. | ||
When a process is started, Windows will combine the `User` `Path` env var with the `System` `Path` env var. | ||
However, for other env vars if the `User` env var exists, a new process will have that value only even if a `Machine` env var | ||
with the same name exists. | ||
In this case, the `User` version of the env var is preferred. | ||
In the changes detailed below, `PSModulePath` adopts the `Path` behavior to have a combined value from `User` and `System` versions of that env var. | ||
|
||
Change would be on Windows: | ||
|
||
- Retrieve user `PSModulePath` env var from registry | ||
- Compare to process inherited `PSModulePath` env var | ||
- If the same: | ||
- Append the `System` `PSModulePath` to the end following the semantics of the `Path` env var | ||
- The Windows system32 path comes from the machine defined `PSModulePath` so does not need to be added explicitly | ||
- If different, treat as though user explicitly modified it and don't append `System` `PSModulePath` | ||
- Prefix with PS7 user, system, and $PSHOME paths in that order | ||
- If `powershell.config.json` contains a user scoped `PSModulePath`, use that instead of the default for the user | ||
- If `powershell.config.json` contains a system scoped `PSModulePath`, use that instead of the default for the system | ||
|
||
Unix systems don't have a separation of `User` and `System` env vars so `PSModulePath` is inherited and PS7 specific paths are prefixed if not | ||
already existing. | ||
|
||
### Starting Windows PowerShell from PowerShell 7 Implementation | ||
|
||
Note that Windows PowerShell here means both `powershell.exe` and `powershell_ise.exe`. | ||
SteveL-MSFT marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
Copy process `$env:PSModulePath` as `WinPSModulePath`: | ||
|
||
- Remove PS7 `User` module path | ||
- Remove PS7 `System` module path | ||
- Remove PS7 `$PSHOME` module path | ||
|
||
Use that `WinPSModulePath` when starting Windows PowerShell. | ||
|
||
### Starting PowerShell 7 from Windows PowerShell | ||
|
||
The PowerShell 7 startup continues as-is with the addition of inheriting paths Windows PowerShell have added. | ||
Since the PS7 specific paths are prefixed, there is no functional issue. | ||
|
||
### Starting PowerShell 6 from PowerShell 7 | ||
|
||
PowerShell Core 6 clobbers `$env:PSModulePath` and no changes will be made. | ||
|
||
### Starting PowerShell 7 from PowerShell 6 | ||
|
||
The PowerShell 7 startup continues as-is with the addition of inheriting paths PowerShell Core 6 have added. | ||
Since the PS7 specific paths are prefixed, there is no functional issue. | ||
|
||
## Alternate Proposals and Considerations | ||
|
||
There was a proposal to cache the inherited `$env:PSModulePath` on startup and pass it to Windows PowerShell when started. | ||
However, this would not reflect any changes the user made and expect to be inherited by the child process. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.