Skip to content

Commit c2ed0e8

Browse files
AndrewSteveL-MSFTjoeyaiello
authored
Accept RFC0050 as Final - Importing Windows PowerShell modules in PowerShell Core (#226)
* Initial draft of WindowsPS-Compatibility-Utilities * fixed some typos * fixed some typos 2 * Added example * WindowsPS-Compatibility-Utilities * WindowsPS-Compatibility-Utilities * WindowsPS-Compatibility-Utilities * Removed special Import-Module switch * Update 1 * Update 2 * Update 3 * typo - compatible Co-Authored-By: Steve Lee <[email protected]> * typo - familiar Co-Authored-By: Steve Lee <[email protected]> * typo - graceful Co-Authored-By: Steve Lee <[email protected]> * Importing-Windows-PowerShell-modules-in-PowerShell-Core * Addressed feedback * formatting fixes * formatting fixes 2 * Added module blacklist * Change "blacklist" to "deny list" * Update 2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md Co-Authored-By: Joey Aiello <[email protected]> * Prep RFC0050 for merging (WinPS Compat Layer) Unanimous consensus to accept from the Committee Co-authored-by: Steve Lee <[email protected]> Co-authored-by: Joey Aiello <[email protected]>
1 parent a4f08ae commit c2ed0e8

File tree

1 file changed

+107
-0
lines changed

1 file changed

+107
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
---
2+
RFC: 0050
3+
Author: Andrew Menagarishvili
4+
Status: Final
5+
SupercededBy:
6+
Version: 0.1
7+
Area: Language
8+
Comments Due: 10/10/2019
9+
Plan to implement: Yes
10+
---
11+
12+
# Importing Windows PowerShell modules in PowerShell Core
13+
14+
One of the big factors preventing existing Windows PowerShell users from moving to PowerShell Core has been cmdlet coverage. Specifically being able to use existing Windows PowerShell modules in PowerShell Core. Non-compatibility is due to the different .NET runtimes used between Windows PowerShell and PowerShell Core. Ease of UX is important when addressing this problem - working with 'WindowsPS-only' modules from PS Core should not be any different than working with 'PS Core - compatible' modules. Also this should not require any setup from the user.
15+
16+
## Motivation
17+
18+
As a PowerShell user,
19+
I can use modules written for Windows PowerShell in PowerShell Core,
20+
so that I could migrate from Windows PowerShell to PowerShell Core.
21+
22+
## New User Experience
23+
24+
Example that shows using commands from 'WindowsPS-only' module located in `System32` module path in PS Core:
25+
```PowerShell
26+
PS C:\> $PSVersionTable.PSEdition
27+
Core
28+
PS C:\> Import-Module DesktopOnlyModuleOnSystem32ModulePath
29+
WARNING: Module DesktopOnlyModuleOnSystem32ModulePath is loaded in Windows PowerShell using WinPSCompatSession remoting session; please note that all parameter values and results of commands from this module will be deserialized objects. If you want to load this module into PowerShell Core please use Import-Module -SkipEditionCheck syntax.
30+
PS C:\> (Get-Module DesktopOnlyModuleOnSystem32ModulePath).CompatiblePSEditions
31+
Desktop
32+
PS C:\> DesktopOnlyModuleOnSystem32ModulePathFunction
33+
Success
34+
```
35+
Proof-of-concept test was successfull.
36+
37+
## Current User Experience
38+
39+
For reference, here is current behaviour that this RFC is targeting to change:
40+
```PowerShell
41+
PS C:\> $PSVersionTable.PSEdition
42+
Core
43+
PS C:\> Import-Module DesktopOnlyModuleOnSystem32ModulePath
44+
Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\DesktopOnlyModuleOnSystem32ModulePath\DesktopOnlyModuleOnSystem32ModulePath.psd1' does not support current PowerShell edition 'Core'. Its supported editions are 'Desktop'. Use 'Import-Module -SkipEditionCheck' to ignore the compatibility of this module.
45+
```
46+
47+
## Specification
48+
49+
Today a module manifest (since Windows PowerShell 5) may contain a `CompatiblePSEditions` property to indicate if it is compatible with PowerShell Core (value of `Core`) or Windows PowerShell (value of `Desktop`). If `CompatiblePSEditions` property is missing then the value of `Desktop` is assumed.<br />
50+
Functionality of this RFC will replace showing of the `PSEditionNotSupported` error message (`Module '{0}' does not support current PowerShell edition '{1}'. Its supported editions are '{2}'. Use 'Import-Module -SkipEditionCheck' to ignore the compatibility of this module.`) in scenarios where it is currently displayed:<br />
51+
During `Import-Module` a module will be loaded into a separate Windows PowerShell process instead of current PowerShell Core if:<br />
52+
(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing))<br />
53+
If this condition is detected PowerShell Core:
54+
1. creates PS Remoting session `WinPSCompatSession` (unless it already exists) using redirected process streams transport (same one used by PS jobs). Internally this creates hidden `WindowsPS Compatibility` Windows PS process.
55+
2. generates local proxy module/commands using `WinPSCompatSession` remoting session and code of `Import-Module -PSSession` cmdlet;
56+
3. when 'WindowsPS-only' module unload request is detected, if no other module is using `WinPSCompatSession` remoting session - it is closed (this also closes remote Windows PS process).
57+
58+
Loading a module into `WinPSCompatSession` can be forced regardless of module path or value of `CompatiblePSEditions` manifest property using `-UseWindowsPowerShell` parameter of `Import-Module`.<br />
59+
New functionality should also be supported during module autoload / command discovery.<br />
60+
Loading of modules into `WinPSCompat` should be tracked in telemetry separately from loading other modules so `TelemetryType.WinCompatModuleLoad` needs to be added.
61+
62+
### PS Remoting Transport
63+
64+
Redirected process streams transport (same one used by PS jobs) is to be used for connections to remote Windows PS process.
65+
A new WindowsPS-specific parameter set will be added to New-PSSession: `New-PSSession -UseWindowsPowerShell [-Name <string[]>]`
66+
Process streams transport automatically manages underlying process, so the lifetime of the `WindowsPS Compatibility` Windows PS process is the same as remoting session that owns it.
67+
68+
### Module deny list
69+
70+
This feature has a significant performance cost - a Windows PS process needs to be started and PS Remoting channel established. This can be a problem in some cases considering this feature also loads modules automatically during command discovery.
71+
Some modules don't work well with de/serialized objects (e.g. pipeline cmdlet combinations of 'Hyper-V' module);<br />
72+
Also there are cases when user never intended to load a module using this feature: for example, using any '-Job' cmdlet tries to load (and currently quietly fails) PS-Core-incompatible 'PSScheduledJob' module. With this feature enabled, 'PSScheduledJob' module is getting successfully loaded even though user never wanted it.<br />
73+
For such cases it is necessary to implement a module deny list.<br />
74+
For modules in the deny list this feature will not engage (and current behavior of generating 'PSEditionNotSupported' error will be maintained).<br />
75+
Module deny list defined using a 'WindowsPowerShellCompatibilityModuleDenyList' setting in 'powershell.config.json' so that user can change it when needed.
76+
77+
Going forward, we will continue to update this list if any modules are discovered to have problems operating in this compatibility layer.
78+
79+
### Lifetime of 'compatibility' Windows PowerShell process and module
80+
81+
Overall RFC goal is to have familiar 'local module' user experience even though actual operations are working with a module in a separate 'compatibility' process. This drives following:
82+
83+
1. One 'compatibility' Windows PowerShell process corresponds to one local PowerShell Core process. E.g. if a same user creates 2 local PowerShell Core processes and loads 'WindowsPS-only' module in each one, this will result in creating 2 Windows PS processes and loading the actuall module in each one of them.
84+
2. Lifetime of the module on 'compatibility' side (Windows PowerShell) should be the same as on local side (PS Core). This is important because some modules save their global state in-between command calls.
85+
* Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in 'compatibility' Windows PS process as it would have been done locally on an compartible module. In addition, this will create `WindowsPS Compatibility` Windows PS process if one does not already exist.
86+
* Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in 'compatibility' Windows PS process as it would have been done locally on an compartible module. In addition, this will remove `WindowsPS Compatibility` Windows PS process if it is no longer needed.
87+
3. When removing a module, there is an `OnRemove` event on the module that will execute. This event allows Compat proxy module to react to being removed and perform cleanup of 'compatibility' process if necessary.
88+
4. PS process exit does Not perform graceful cleanup of modules, so it needs to be handled separately. There is an event that allows to react to the closing of the PowerShell process (to do 'compatibility' process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript`
89+
90+
### Objects returned by remote operations
91+
92+
With PS Remoting objects returned from remote 'compatibility' side are not actual `live` objects. This will be the same in case of this RFC. A warning will be generated every time a module is imported using this new functionality; also documentation will make sure that users understand that even though the experience will look like they are working with 'WindowsPS-only' modules locally, objects returned by these modules are deserialized copies.
93+
94+
## Alternate Proposals and Considerations
95+
96+
### Scenarios that need improvement
97+
98+
1. Ideally there should be 1-to-1 runspace afinity between PSCore and WinPS processes; currently this is many(runspaces of a single PSCore process)-to-1(runspace of a single WinPS process), which in some cases may cause conflicts.
99+
2. PS providers are not supported across remoting boundaries.
100+
101+
### Windows PowerShell Compatibility module
102+
103+
[Windows PowerShell Compatibility module](https://github.com/PowerShell/WindowsCompatibility) was initial step toward solving the problem of using WindowsPS modules in PS Core. It has following drawbacks:
104+
- It uses WinRM-based PS remoting which:
105+
+ requires setup
106+
+ not the best transport performance-wise
107+
- Introduces additional cmdlets to work with 'WindowsPS-only' modules, i.e. does not have transparent user experience.

0 commit comments

Comments
 (0)