Skip to content

Commit a4f08ae

Browse files
RFC0049 - PSModulePath behavior in PS7 (#233)
* Draft of PSModulePath behavior in PS7 * clarify PS7 current behavior * remove unncessary steps in constructing WinPS PSModulePath * clarify `Windows` module path on PS7 startup * Update adding more details. Fix examples to be consistent. * Prep RFC0049 (PSModulePath with WinPS/PSCore) for merge Co-authored-by: Joey Aiello <[email protected]>
1 parent 4b984df commit a4f08ae

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

5-Final/RFC0049-PSModulePath.md

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
---
2+
RFC: 0049
3+
Author: Steve Lee
4+
Status: Draft
5+
SupercededBy: n/a
6+
Version: 1.0
7+
Area: Engine
8+
Comments Due: 11/30
9+
Plan to implement: Yes
10+
---
11+
12+
# PSModulePath When Starting PowerShell within PowerShell
13+
14+
When starting PowerShell from a different version of PowerShell, the PSModulePath
15+
should reflect the module search path and only include segments appropriate for
16+
the version of PowerShell being started.
17+
18+
## Motivation
19+
20+
As a PowerShell User,
21+
I can start a different version of PowerShell within PowerShell,
22+
so that I can do things required by that specific version of PowerShell.
23+
24+
## User Experience
25+
26+
### Starting Windows PowerShell from PowerShell 7
27+
28+
```powershell
29+
PS7> $env:PSModulePath.split(';')
30+
C:\Users\user\Documents\PowerShell\Modules
31+
C:\Program Files\PowerShell\Modules
32+
c:\program files\powershell\7-preview\Modules
33+
C:\Program Files\WindowsPowerShell\Modules
34+
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
35+
36+
PS7> powershell -noprofile
37+
WinPS> $env:PSModulePath.split(';')
38+
C:\Users\user\Documents\WindowsPowerShell\Modules
39+
C:\Program Files\WindowsPowerShell\Modules
40+
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
41+
```
42+
43+
### Starting Windows PowerShell from PowerShell 7 with additions by user
44+
45+
Here a custom `C:\MyModules` is added
46+
47+
```powershell
48+
PS7> $env:PSModulePath.split(';')
49+
C:\Users\user\Documents\PowerShell\Modules
50+
C:\Program Files\PowerShell\Modules
51+
c:\program files\powershell\7-preview\Modules
52+
C:\Program Files\WindowsPowerShell\Modules
53+
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
54+
C:\MyModules
55+
56+
PS7> powershell -noprofile
57+
WinPS> $env:PSModulePath.split(';')
58+
C:\Program Files\WindowsPowerShell\Modules
59+
C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
60+
C:\MyModules
61+
```
62+
63+
### Starting Windows PowerShell from PowerShell 7 with deletions by user
64+
65+
Here the `System32` path is removed
66+
67+
```powershell
68+
PS7> $env:PSModulePath.split(';')
69+
C:\Users\user\Documents\PowerShell\Modules
70+
C:\Program Files\PowerShell\Modules
71+
c:\program files\powershell\7-preview\Modules
72+
C:\Program Files\WindowsPowerShell\Modules
73+
74+
PS7> powershell -noprofile
75+
WinPS> $env:PSModulePath.split(';')
76+
C:\Program Files\WindowsPowerShell\Modules
77+
```
78+
79+
### Starting Windows PowerShell from PowerShell 7 with additions and deletions by user
80+
81+
Here the `System32` path is removed and the `C:\MyModules` path is added
82+
83+
```powershell
84+
PS7> $env:PSModulePath.split(';')
85+
C:\Users\user\Documents\PowerShell\Modules
86+
C:\Program Files\PowerShell\Modules
87+
c:\program files\powershell\7-preview\Modules
88+
C:\Program Files\WindowsPowerShell\Modules
89+
C:\MyModules
90+
91+
PS7> powershell -noprofile
92+
WinPS> $env:PSModulePath.split(';')
93+
C:\Program Files\WindowsPowerShell\Modules
94+
C:\MyModules
95+
```
96+
97+
## Specification
98+
99+
By default, PowerShell starts with (in order):
100+
101+
| Segment Description | Windows PowerShell example | PowerShell 7 example |
102+
|---------------------|--------------------------------------------------------------------------|---------------------------------------------------|
103+
| User modules | C:\Users\user\Documents\WindowsPowerShell\Modules | C:\Users\user\Documents\PowerShell\Modules |
104+
| System modules | C:\Program Files\WindowsPowerShell\Modules | C:\Program Files\PowerShell\Modules |
105+
| $PSHOME modules | C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules | c:\program files\powershell\7-preview\Modules |
106+
| Windows modules | | C:\WINDOWS\system32\WindowsPowerShell\v1.0\Module |
107+
| App added modules | C:\Program Files (x86)\Microsoft Azure Information Protection\Powershell | |
108+
109+
Currently, applications (or user) adding additional paths to `$env:PSModulePath` are dropped in PowerShell 7.
110+
111+
### Windows PowerShell PSModulePath construction
112+
113+
Windows PowerShell has logic at startup to construct the PSModulePath based on (simplified version):
114+
115+
- If PSModulePath doesn't exist: Combine `User` modules path, `System` modules path, and `$PSHOME` modules path
116+
- If PSModulePath does exist:
117+
- If PSModulePath contains `$PSHOME` modules path:
118+
- `System` modules path is inserted before `$PSHOME` modules path if it's not there
119+
- else:
120+
- Just use `$env:PSModulePath` as-is as user had deliberately removed `$PSHOME`
121+
122+
`User` module path is prefixed only if User scope `$env:PSModulePath` doesn't exist.
123+
Otherwise, it is assumed the user removed it if it's not there already.
124+
125+
There are no changes planned for Windows PowerShell 5.1, so this existing logic is in place.
126+
127+
### PowerShell 7 startup
128+
129+
Currently, PSCore6 doesn't use contents of `$env:PSModulePath` if it detects it was started from PowerShell
130+
and simply overwrites it with `User` modules path + `System` modules path + `$PSHOME` modules path + `Windows` modules path.
131+
132+
Intent is to have `PSModulePath` behave how `Path` env var works on Windows.
133+
`Path` on Windows is treated differently from other env vars.
134+
When a process is started, Windows will combine the `User` `Path` env var with the `System` `Path` env var.
135+
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
136+
with the same name exists.
137+
In this case, the `User` version of the env var is preferred.
138+
In the changes detailed below, `PSModulePath` adopts the `Path` behavior to have a combined value from `User` and `System` versions of that env var.
139+
140+
Change would be on Windows:
141+
142+
- Retrieve user `PSModulePath` env var from registry
143+
- Compare to process inherited `PSModulePath` env var
144+
- If the same:
145+
- Append the `System` `PSModulePath` to the end following the semantics of the `Path` env var
146+
- The Windows system32 path comes from the machine defined `PSModulePath` so does not need to be added explicitly
147+
- If different, treat as though user explicitly modified it and don't append `System` `PSModulePath`
148+
- Prefix with PS7 user, system, and $PSHOME paths in that order
149+
- If `powershell.config.json` contains a user scoped `PSModulePath`, use that instead of the default for the user
150+
- If `powershell.config.json` contains a system scoped `PSModulePath`, use that instead of the default for the system
151+
152+
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
153+
already existing.
154+
155+
### Starting Windows PowerShell from PowerShell 7 Implementation
156+
157+
Note that Windows PowerShell here means both `powershell.exe` and `powershell_ise.exe`.
158+
159+
Copy process `$env:PSModulePath` as `WinPSModulePath`:
160+
161+
- Remove PS7 `User` module path
162+
- Remove PS7 `System` module path
163+
- Remove PS7 `$PSHOME` module path
164+
165+
Use that `WinPSModulePath` when starting Windows PowerShell.
166+
167+
### Starting PowerShell 7 from Windows PowerShell
168+
169+
The PowerShell 7 startup continues as-is with the addition of inheriting paths Windows PowerShell have added.
170+
Since the PS7 specific paths are prefixed, there is no functional issue.
171+
172+
### Starting PowerShell 6 from PowerShell 7
173+
174+
PowerShell Core 6 clobbers `$env:PSModulePath` and no changes will be made.
175+
176+
### Starting PowerShell 7 from PowerShell 6
177+
178+
The PowerShell 7 startup continues as-is with the addition of inheriting paths PowerShell Core 6 have added.
179+
Since the PS7 specific paths are prefixed, there is no functional issue.
180+
181+
## Alternate Proposals and Considerations
182+
183+
There was a proposal to cache the inherited `$env:PSModulePath` on startup and pass it to Windows PowerShell when started.
184+
However, this would not reflect any changes the user made and expect to be inherited by the child process.

0 commit comments

Comments
 (0)