From c697c0c688be8787648c080538f1833904a67974 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Thu, 5 Sep 2019 15:26:30 -0700 Subject: [PATCH 01/22] Initial draft of WindowsPS-Compatibility-Utilities --- ...FCNNN-WindowsPS-Compatibility-Utilities.md | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md new file mode 100644 index 00000000..6104b3e8 --- /dev/null +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -0,0 +1,65 @@ +--- +RFC: +Author: Andrew Menagarishvili +Status: Draft +SupercededBy: +Version: 0.1 +Area: Language +Comments Due: 10/10/2019 +Plan to implement: Yes +--- + +# Windows PowerShell Compatibility Utilities + +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. Ease of UX is important here - working with 'WindowsPS-only' modules from PS Core should not be any different than working with 'PS Core - compartible' modules. Also this should not require any setup from the user. + +## Motivation + + As a PowerShell user, + I can use modules written for Windows PowerShell in PowerShell Core, + so that I could migrate from Windows PowerShell to PowerShell Core. + +## User Experience + +Proof-of-concept test was successfull. +Examples will be added shortly... + +## Specification + +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`). +Absense of `Core` value in `CompatiblePSEditions` during module import signals to PS Core that it should process the module as described in this RFC. + +When Import-Module in PS Core detects that user is attempting to load 'WindowsPS-only' module: + 1. it creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) + 2. creates PS Remoting connection to its IPC pipe + 3. loads the module in remote Windows PS process + 4. generate local proxy module/commands using IPC remoting connection and Import-PSSession cmdlet + 5. when 'WindowsPS-only' module unload request is detected - unload module in remote process, close PS remoting channel, close remote process + +### PS Remoting Transport + +IPC / Named Pipe is to be used for connections to remote PowerShell process. Today a named pipe listener is created with each Windows PowerShell process. IPC transport has good performance and secured endpoints, however (unlike, for example, SSH transport) it is not currently supported by New-PSSession. +So a new IPC parameter set will be added to New-PSSession. + +### Lifetime of remote Windows PowerShell process and module + +Overall RFC goal is to have farmiliar 'local module' user experience even though actuall operations are working with a module in a remote process. This drives following: + +1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. +2. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. +2. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. + +### Objects returned by remote opeartions + +With PS Remoting objects returned from remote side are not actual `live` objects. This will be the same in case of this RFC. 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. + +## Alternate Proposals and Considerations + +### Windows PowerShell Compatibility module + +[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: +1. It uses WinRM-based PS remoting which: + 1. requires setup + 1. not the best transport performance-wise +1. Introduces additional cmdlets to work with 'WindowsPS-only' modules, i.e. does not have transparent user experience. + From 41b950fe22e77b32743dfc9c3c48ed1ed0ac5318 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Thu, 5 Sep 2019 15:43:58 -0700 Subject: [PATCH 02/22] fixed some typos --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 6104b3e8..4cd94542 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -33,7 +33,7 @@ When Import-Module in PS Core detects that user is attempting to load 'WindowsPS 1. it creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) 2. creates PS Remoting connection to its IPC pipe 3. loads the module in remote Windows PS process - 4. generate local proxy module/commands using IPC remoting connection and Import-PSSession cmdlet + 4. generates local proxy module/commands using IPC remoting connection and Import-PSSession cmdlet 5. when 'WindowsPS-only' module unload request is detected - unload module in remote process, close PS remoting channel, close remote process ### PS Remoting Transport @@ -49,7 +49,7 @@ Overall RFC goal is to have farmiliar 'local module' user experience even though 2. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. 2. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. -### Objects returned by remote opeartions +### Objects returned by remote operations With PS Remoting objects returned from remote side are not actual `live` objects. This will be the same in case of this RFC. 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. @@ -59,7 +59,7 @@ With PS Remoting objects returned from remote side are not actual `live` objects [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: 1. It uses WinRM-based PS remoting which: - 1. requires setup - 1. not the best transport performance-wise + i. requires setup + ii. not the best transport performance-wise 1. Introduces additional cmdlets to work with 'WindowsPS-only' modules, i.e. does not have transparent user experience. From 7fdc10fd102abb29f1fb1981d843fc3f7146b7bb Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Thu, 5 Sep 2019 15:46:33 -0700 Subject: [PATCH 03/22] fixed some typos 2 --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 4cd94542..013d7ccd 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -47,7 +47,7 @@ Overall RFC goal is to have farmiliar 'local module' user experience even though 1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. 2. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. -2. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. +3. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. ### Objects returned by remote operations @@ -58,8 +58,8 @@ With PS Remoting objects returned from remote side are not actual `live` objects ### Windows PowerShell Compatibility module [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: -1. It uses WinRM-based PS remoting which: - i. requires setup - ii. not the best transport performance-wise -1. Introduces additional cmdlets to work with 'WindowsPS-only' modules, i.e. does not have transparent user experience. +- It uses WinRM-based PS remoting which: + + requires setup + + not the best transport performance-wise +- Introduces additional cmdlets to work with 'WindowsPS-only' modules, i.e. does not have transparent user experience. From 6461dd6cda6a0695343ba0fa5c7291d7c741e74b Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 6 Sep 2019 15:17:33 -0700 Subject: [PATCH 04/22] Added example --- ...FCNNN-WindowsPS-Compatibility-Utilities.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 013d7ccd..21e0ee89 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -21,8 +21,25 @@ One of the big factors preventing existing Windows PowerShell users from moving ## User Experience +Example that shows using commands from 'WindowsPS-only' module in PS Core: +```PowerShell +PS C:\> $PSVersionTable.PSEdition +Core +PS C:\> Import-Module DesktopOnlyModule +PS C:\> (Get-Module DesktopOnlyModule).CompatiblePSEditions +Desktop +PS C:\> DesktopOnlyModuleFunction +Success +``` Proof-of-concept test was successfull. -Examples will be added shortly... + +For reference, here is current behaviour that this RFC is targeting to change: +```PowerShell +PS C:\> $PSVersionTable.PSEdition +Core +PS C:\> Import-Module DesktopOnlyModule +Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\DesktopOnlyModule\DesktopOnlyModule.psd1' does not support current PowerShell edition 'Core'. Its supported editions are 'Desktop'. Use 'Import-Module -SkipEditionCheck' to ignore the compatibility of this module. +``` ## Specification From ac4591bf94b0fb0d48c311c7c149f97a67805d29 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 13:02:19 -0700 Subject: [PATCH 05/22] WindowsPS-Compatibility-Utilities --- ...FCNNN-WindowsPS-Compatibility-Utilities.md | 33 ++++++++++++++++--- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 21e0ee89..bbb17815 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -25,7 +25,7 @@ Example that shows using commands from 'WindowsPS-only' module in PS Core: ```PowerShell PS C:\> $PSVersionTable.PSEdition Core -PS C:\> Import-Module DesktopOnlyModule +PS C:\> Import-Module DesktopOnlyModule -AsWindowsCompatibility PS C:\> (Get-Module DesktopOnlyModule).CompatiblePSEditions Desktop PS C:\> DesktopOnlyModuleFunction @@ -44,19 +44,40 @@ Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\Deskt ## Specification 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`). -Absense of `Core` value in `CompatiblePSEditions` during module import signals to PS Core that it should process the module as described in this RFC. +Initial proposal was that absense of `Core` value in `CompatiblePSEditions` during module import would signal to PS Core that it should process the module as described in this RFC, however PS Core still allows to load non-`Core` modules without any warnings if they are not located under System32 module path. This means that `CompatiblePSEditions` property can not be used for deciding whether to load a module as WinPS module or not. +Current plan is to add a new `-AsWindowsCompatibility` parameter for `Import-Module`. -When Import-Module in PS Core detects that user is attempting to load 'WindowsPS-only' module: +When Import-Module in PS Core detects that user is attempting to load a module with `-AsWindowsCompatibility` parameter: 1. it creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) 2. creates PS Remoting connection to its IPC pipe 3. loads the module in remote Windows PS process - 4. generates local proxy module/commands using IPC remoting connection and Import-PSSession cmdlet + 4. generates local proxy module/commands using IPC remoting connection and `Import-PSSession` cmdlet 5. when 'WindowsPS-only' module unload request is detected - unload module in remote process, close PS remoting channel, close remote process ### PS Remoting Transport IPC / Named Pipe is to be used for connections to remote PowerShell process. Today a named pipe listener is created with each Windows PowerShell process. IPC transport has good performance and secured endpoints, however (unlike, for example, SSH transport) it is not currently supported by New-PSSession. -So a new IPC parameter set will be added to New-PSSession. +So a new IPC-specific parameter set will be added to New-PSSession: `New-PSSession [-Name ] -ProcessId ` +Here is the pseudo-code that shows the essence of proposed implementation of a new parameter set in New-PSSession: +```csharp +string WindowsPS_AppDomainName = GetPSHostProcessInfoCommand.GetAppDomainNamesFromProcessId(WindowsPS_ProcessId); +NamedPipeConnectionInfo connectionInfo = new NamedPipeConnectionInfo(WindowsPS_ProcessId, WindowsPS_AppDomainName); +TypeTable typeTable = TypeTable.LoadDefaultTypeFiles(); +RemoteRunspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo, this.Host, typeTable) as RemoteRunspace; +remoteRunspace.Name = NamedPipeRunspaceName; +remoteRunspace.ShouldCloseOnPop = true +try +{ + remoteRunspace.Open(); +} +catch (RuntimeException e) +{ + // handle connection errors +} +PSSession remotePSSession = new PSSession(remoteRunspace); +this.RunspaceRepository.Add(remotePSSession); +WriteObject(remotePSSession); +``` ### Lifetime of remote Windows PowerShell process and module @@ -65,6 +86,8 @@ Overall RFC goal is to have farmiliar 'local module' user experience even though 1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. 2. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. 3. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. +4. 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 remote process if necessary. +5. PS process exit does Not perform gracefull 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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` ### Objects returned by remote operations From 5e9faa83247d9dd85b9f248cc1aae401af3fa173 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 13:12:49 -0700 Subject: [PATCH 06/22] WindowsPS-Compatibility-Utilities --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index bbb17815..7ffeea2d 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -84,10 +84,11 @@ WriteObject(remotePSSession); Overall RFC goal is to have farmiliar 'local module' user experience even though actuall operations are working with a module in a remote process. This drives following: 1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. -2. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. -3. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. -4. 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 remote process if necessary. -5. PS process exit does Not perform gracefull 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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` +2. Lifetime of the module on remote side (Windows PS) should be the same as on local side (PS Core). This is important because some modules save their global state in-between command calls. + 1. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. + 2. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. +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 remote process if necessary. +4. PS process exit does Not perform gracefull 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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` ### Objects returned by remote operations From 988c065f2166a3f5a797f78ee73245c087df89fd Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 13:13:58 -0700 Subject: [PATCH 07/22] WindowsPS-Compatibility-Utilities --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 7ffeea2d..fc7fd2f1 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -85,8 +85,8 @@ Overall RFC goal is to have farmiliar 'local module' user experience even though 1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. 2. Lifetime of the module on remote side (Windows PS) should be the same as on local side (PS Core). This is important because some modules save their global state in-between command calls. - 1. Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. - 2. Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. + * Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. + * Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. 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 remote process if necessary. 4. PS process exit does Not perform gracefull 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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` From 6b9a715ed7e91d1a85cd93b572c72be2d2f7f23b Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 14:27:22 -0700 Subject: [PATCH 08/22] Removed special Import-Module switch --- ...FCNNN-WindowsPS-Compatibility-Utilities.md | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index fc7fd2f1..19fee625 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -21,14 +21,14 @@ One of the big factors preventing existing Windows PowerShell users from moving ## User Experience -Example that shows using commands from 'WindowsPS-only' module in PS Core: +Example that shows using commands from 'WindowsPS-only' module located in `System32` module path in PS Core: ```PowerShell PS C:\> $PSVersionTable.PSEdition Core -PS C:\> Import-Module DesktopOnlyModule -AsWindowsCompatibility -PS C:\> (Get-Module DesktopOnlyModule).CompatiblePSEditions +PS C:\> Import-Module DesktopOnlyModuleOnSystem32ModulePath +PS C:\> (Get-Module DesktopOnlyModuleOnSystem32ModulePath).CompatiblePSEditions Desktop -PS C:\> DesktopOnlyModuleFunction +PS C:\> DesktopOnlyModuleOnSystem32ModulePathFunction Success ``` Proof-of-concept test was successfull. @@ -37,18 +37,18 @@ For reference, here is current behaviour that this RFC is targeting to change: ```PowerShell PS C:\> $PSVersionTable.PSEdition Core -PS C:\> Import-Module DesktopOnlyModule -Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\DesktopOnlyModule\DesktopOnlyModule.psd1' does not support current PowerShell edition 'Core'. Its supported editions are 'Desktop'. Use 'Import-Module -SkipEditionCheck' to ignore the compatibility of this module. +PS C:\> Import-Module DesktopOnlyModuleOnSystem32ModulePath +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. ``` ## Specification -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`). -Initial proposal was that absense of `Core` value in `CompatiblePSEditions` during module import would signal to PS Core that it should process the module as described in this RFC, however PS Core still allows to load non-`Core` modules without any warnings if they are not located under System32 module path. This means that `CompatiblePSEditions` property can not be used for deciding whether to load a module as WinPS module or not. -Current plan is to add a new `-AsWindowsCompatibility` parameter for `Import-Module`. - -When Import-Module in PS Core detects that user is attempting to load a module with `-AsWindowsCompatibility` parameter: - 1. it creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) +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. +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: +During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if: +(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing)) +If this condition is detected PowerShell Core: + 1. creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) 2. creates PS Remoting connection to its IPC pipe 3. loads the module in remote Windows PS process 4. generates local proxy module/commands using IPC remoting connection and `Import-PSSession` cmdlet From 6aec095ef9ef968730fff0dd2be4446b386f5cef Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 14:30:05 -0700 Subject: [PATCH 09/22] Update 1 --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 19fee625..18fb1415 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -45,8 +45,11 @@ Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\Deskt 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. 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: + During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if: -(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing)) + +* (A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing)) + If this condition is detected PowerShell Core: 1. creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) 2. creates PS Remoting connection to its IPC pipe From c6445e41640b99b3363018fd95353406e3415712 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 14:31:28 -0700 Subject: [PATCH 10/22] Update 2 --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 18fb1415..5e870879 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -43,12 +43,10 @@ Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\Deskt ## Specification -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. -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: - -During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if: - -* (A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing)) +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. +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: +During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if: +(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing)) If this condition is detected PowerShell Core: 1. creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) From ff270c31a9102d86596a55972cc46482c5ab5a0e Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Fri, 13 Sep 2019 14:34:28 -0700 Subject: [PATCH 11/22] Update 3 --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 5e870879..c3ab5e69 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -43,11 +43,10 @@ Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\Deskt ## Specification -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. -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: -During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if: -(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing)) - +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.
+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:
+During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if:
+(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing))
If this condition is detected PowerShell Core: 1. creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) 2. creates PS Remoting connection to its IPC pipe From bf27e930643e0213a2bba99a9903bc7882f60db5 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 19 Sep 2019 13:50:31 -0700 Subject: [PATCH 12/22] typo - compatible Co-Authored-By: Steve Lee --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index c3ab5e69..9783308c 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -11,7 +11,7 @@ Plan to implement: Yes # Windows PowerShell Compatibility Utilities -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. Ease of UX is important here - working with 'WindowsPS-only' modules from PS Core should not be any different than working with 'PS Core - compartible' modules. Also this should not require any setup from the user. +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. Ease of UX is important here - 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. ## Motivation From 34e6a8f646bc26b5a7cc07e24cebfe8ae9c8934f Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 19 Sep 2019 13:51:29 -0700 Subject: [PATCH 13/22] typo - familiar Co-Authored-By: Steve Lee --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index 9783308c..f1330adf 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -81,7 +81,7 @@ WriteObject(remotePSSession); ### Lifetime of remote Windows PowerShell process and module -Overall RFC goal is to have farmiliar 'local module' user experience even though actuall operations are working with a module in a remote process. This drives following: +Overall RFC goal is to have familiar 'local module' user experience even though actual operations are working with a module in a remote process. This drives following: 1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. 2. Lifetime of the module on remote side (Windows PS) should be the same as on local side (PS Core). This is important because some modules save their global state in-between command calls. From b50a11042ec04357c066c7f96a6dd80d1c2da25c Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 19 Sep 2019 13:51:57 -0700 Subject: [PATCH 14/22] typo - graceful Co-Authored-By: Steve Lee --- 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md index f1330adf..7d5a288e 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md @@ -88,7 +88,7 @@ Overall RFC goal is to have familiar 'local module' user experience even though * Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. * Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. 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 remote process if necessary. -4. PS process exit does Not perform gracefull 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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` +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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` ### Objects returned by remote operations From 80847964badba7522b5db6b9e70db8ce779f3ce8 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Thu, 19 Sep 2019 14:49:27 -0700 Subject: [PATCH 15/22] Importing-Windows-PowerShell-modules-in-PowerShell-Core --- ...s-PowerShell-modules-in-PowerShell-Core.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) rename 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md => 2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md (65%) diff --git a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md similarity index 65% rename from 1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md rename to 2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index 7d5a288e..4276bd67 100644 --- a/1-Draft/RFCNNN-WindowsPS-Compatibility-Utilities.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -9,9 +9,9 @@ Comments Due: 10/10/2019 Plan to implement: Yes --- -# Windows PowerShell Compatibility Utilities +# Importing Windows PowerShell modules in PowerShell Core -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. Ease of UX is important here - 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. +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. ## Motivation @@ -26,6 +26,7 @@ Example that shows using commands from 'WindowsPS-only' module located in `Syste PS C:\> $PSVersionTable.PSEdition Core PS C:\> Import-Module DesktopOnlyModuleOnSystem32ModulePath +VERBOSE: Please note that module 'DesktopOnlyModuleOnSystem32ModulePath' is imported in a remote Windows PowerShell session, so all objects that are returned by commands from this module are deserialized and are not 'live' objects. PS C:\> (Get-Module DesktopOnlyModuleOnSystem32ModulePath).CompatiblePSEditions Desktop PS C:\> DesktopOnlyModuleOnSystem32ModulePathFunction @@ -57,15 +58,13 @@ If this condition is detected PowerShell Core: ### PS Remoting Transport IPC / Named Pipe is to be used for connections to remote PowerShell process. Today a named pipe listener is created with each Windows PowerShell process. IPC transport has good performance and secured endpoints, however (unlike, for example, SSH transport) it is not currently supported by New-PSSession. -So a new IPC-specific parameter set will be added to New-PSSession: `New-PSSession [-Name ] -ProcessId ` +So a new IPC-specific parameter set will be added to New-PSSession: `New-PSSession -ProcessId [-Name ] [-AppDomainName ]` Here is the pseudo-code that shows the essence of proposed implementation of a new parameter set in New-PSSession: ```csharp -string WindowsPS_AppDomainName = GetPSHostProcessInfoCommand.GetAppDomainNamesFromProcessId(WindowsPS_ProcessId); NamedPipeConnectionInfo connectionInfo = new NamedPipeConnectionInfo(WindowsPS_ProcessId, WindowsPS_AppDomainName); TypeTable typeTable = TypeTable.LoadDefaultTypeFiles(); RemoteRunspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo, this.Host, typeTable) as RemoteRunspace; remoteRunspace.Name = NamedPipeRunspaceName; -remoteRunspace.ShouldCloseOnPop = true try { remoteRunspace.Open(); @@ -77,22 +76,23 @@ catch (RuntimeException e) PSSession remotePSSession = new PSSession(remoteRunspace); this.RunspaceRepository.Add(remotePSSession); WriteObject(remotePSSession); +// In case of 'Windows PS Compatibility' scenario, Import-PSSession is then run on remotePSSession to generate proxy cmdlets. ``` -### Lifetime of remote Windows PowerShell process and module +### Lifetime of 'compatibility' Windows PowerShell process and module -Overall RFC goal is to have familiar 'local module' user experience even though actual operations are working with a module in a remote process. This drives following: +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: -1. One remote Windows PS process corresponds to one local PS Core process. E.g. if a same user creates 2 local PS 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. -2. Lifetime of the module on remote side (Windows PS) should be the same as on local side (PS Core). This is important because some modules save their global state in-between command calls. - * Local Load-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. - * Local Remove-Module for 'WindowsPS-only' module will have same behaviour/effect in remote 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. -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 remote process if necessary. -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 remote Compat process cleanup): `Register-EngineEvent -SourceIdentifier ([System.Management.Automation.PsEngineEvent]::Exiting) -Action $OnRemoveScript` +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. +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. + * 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. + * 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. +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. +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` ### Objects returned by remote operations -With PS Remoting objects returned from remote side are not actual `live` objects. This will be the same in case of this RFC. 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. +With PS Remoting objects returned from remote 'compatibility' side are not actual `live` objects. This will be the same in case of this RFC. 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. ## Alternate Proposals and Considerations From fa9a19caa16e34f387c30a1271a19b8ce0573e86 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Mon, 4 Nov 2019 16:32:37 -0800 Subject: [PATCH 16/22] Addressed feedback --- ...s-PowerShell-modules-in-PowerShell-Core.md | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index 4276bd67..5033a8a5 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -19,14 +19,14 @@ One of the big factors preventing existing Windows PowerShell users from moving I can use modules written for Windows PowerShell in PowerShell Core, so that I could migrate from Windows PowerShell to PowerShell Core. -## User Experience +## New User Experience Example that shows using commands from 'WindowsPS-only' module located in `System32` module path in PS Core: ```PowerShell PS C:\> $PSVersionTable.PSEdition Core PS C:\> Import-Module DesktopOnlyModuleOnSystem32ModulePath -VERBOSE: Please note that module 'DesktopOnlyModuleOnSystem32ModulePath' is imported in a remote Windows PowerShell session, so all objects that are returned by commands from this module are deserialized and are not 'live' objects. +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. PS C:\> (Get-Module DesktopOnlyModuleOnSystem32ModulePath).CompatiblePSEditions Desktop PS C:\> DesktopOnlyModuleOnSystem32ModulePathFunction @@ -34,6 +34,8 @@ Success ``` Proof-of-concept test was successfull. +## Current User Experience + For reference, here is current behaviour that this RFC is targeting to change: ```PowerShell PS C:\> $PSVersionTable.PSEdition @@ -46,38 +48,21 @@ Import-Module : Module 'C:\windows\system32\WindowsPowerShell\v1.0\Modules\Deskt 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.
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:
-During `Import-Module` a module wil be loaded into a separete Windows PowerShell process instead of current PowerShell Core if:
+During `Import-Module` a module will be loaded into a separate Windows PowerShell process instead of current PowerShell Core if:
(A module is located in `System32` module path) and ((`CompatiblePSEditions` is `Desktop`) or (`CompatiblePSEditions` is missing))
If this condition is detected PowerShell Core: - 1. creates a hidden `WindowsPS Compatibility` Windows PS process (unless one already exists) - 2. creates PS Remoting connection to its IPC pipe - 3. loads the module in remote Windows PS process - 4. generates local proxy module/commands using IPC remoting connection and `Import-PSSession` cmdlet - 5. when 'WindowsPS-only' module unload request is detected - unload module in remote process, close PS remoting channel, close remote process + 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. + 2. generates local proxy module/commands using `WinPSCompatSession` remoting session and code of `Import-Module -PSSession` cmdlet; + 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). +Loading a module into `WinPSCompatSession` can be forced regardless of module path or value of `CompatiblePSEditions` manifest property using `-UseWindowsPowerShell` parameter of `Import-Module`. +New functionality should also be supported during module autoload / command discovery. +Loading of modules into `WinPSCompat` should be tracked in Telemetry separately from loading other modules so `TelemetryType.WinCompatModuleLoad` needs to be added. ### PS Remoting Transport -IPC / Named Pipe is to be used for connections to remote PowerShell process. Today a named pipe listener is created with each Windows PowerShell process. IPC transport has good performance and secured endpoints, however (unlike, for example, SSH transport) it is not currently supported by New-PSSession. -So a new IPC-specific parameter set will be added to New-PSSession: `New-PSSession -ProcessId [-Name ] [-AppDomainName ]` -Here is the pseudo-code that shows the essence of proposed implementation of a new parameter set in New-PSSession: -```csharp -NamedPipeConnectionInfo connectionInfo = new NamedPipeConnectionInfo(WindowsPS_ProcessId, WindowsPS_AppDomainName); -TypeTable typeTable = TypeTable.LoadDefaultTypeFiles(); -RemoteRunspace remoteRunspace = RunspaceFactory.CreateRunspace(connectionInfo, this.Host, typeTable) as RemoteRunspace; -remoteRunspace.Name = NamedPipeRunspaceName; -try -{ - remoteRunspace.Open(); -} -catch (RuntimeException e) -{ - // handle connection errors -} -PSSession remotePSSession = new PSSession(remoteRunspace); -this.RunspaceRepository.Add(remotePSSession); -WriteObject(remotePSSession); -// In case of 'Windows PS Compatibility' scenario, Import-PSSession is then run on remotePSSession to generate proxy cmdlets. -``` +Redirected process streams transport (same one used by PS jobs) is to be used for connections to remote Windows PS process. +A new WindowsPS-specific parameter set will be added to New-PSSession: `New-PSSession -UseWindowsPowerShell [-Name ]` +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. ### Lifetime of 'compatibility' Windows PowerShell process and module @@ -92,10 +77,15 @@ Overall RFC goal is to have familiar 'local module' user experience even though ### Objects returned by remote operations -With PS Remoting objects returned from remote 'compatibility' side are not actual `live` objects. This will be the same in case of this RFC. 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. +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. ## Alternate Proposals and Considerations +### Scenarios that need improvement + +1. Ideally there should be 1-to-1 runspace afinity between PSCore and WinPS processes; currently this is many-to-1, which in some cases may cause conflicts. +2. PS providers are not supported across remoting boundaries. + ### Windows PowerShell Compatibility module [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: From 2e97c7876df99afa5357793a7d722e95a6b7cddc Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Mon, 4 Nov 2019 16:39:05 -0800 Subject: [PATCH 17/22] formatting fixes --- ...ng-Windows-PowerShell-modules-in-PowerShell-Core.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index 5033a8a5..eef3c1e2 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -53,10 +53,10 @@ During `Import-Module` a module will be loaded into a separate Windows PowerShel If this condition is detected PowerShell Core: 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. 2. generates local proxy module/commands using `WinPSCompatSession` remoting session and code of `Import-Module -PSSession` cmdlet; - 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). -Loading a module into `WinPSCompatSession` can be forced regardless of module path or value of `CompatiblePSEditions` manifest property using `-UseWindowsPowerShell` parameter of `Import-Module`. -New functionality should also be supported during module autoload / command discovery. -Loading of modules into `WinPSCompat` should be tracked in Telemetry separately from loading other modules so `TelemetryType.WinCompatModuleLoad` needs to be added. + 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).
+Loading a module into `WinPSCompatSession` can be forced regardless of module path or value of `CompatiblePSEditions` manifest property using `-UseWindowsPowerShell` parameter of `Import-Module`.
+New functionality should also be supported during module autoload / command discovery.
+Loading of modules into `WinPSCompat` should be tracked in telemetry separately from loading other modules so `TelemetryType.WinCompatModuleLoad` needs to be added. ### PS Remoting Transport @@ -83,7 +83,7 @@ With PS Remoting objects returned from remote 'compatibility' side are not actua ### Scenarios that need improvement -1. Ideally there should be 1-to-1 runspace afinity between PSCore and WinPS processes; currently this is many-to-1, which in some cases may cause conflicts. +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. 2. PS providers are not supported across remoting boundaries. ### Windows PowerShell Compatibility module From 14eb2f21fb198dabedc72a631e0b89e5a3493355 Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Mon, 4 Nov 2019 16:40:42 -0800 Subject: [PATCH 18/22] formatting fixes 2 --- ...-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index eef3c1e2..40be3655 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -53,7 +53,8 @@ During `Import-Module` a module will be loaded into a separate Windows PowerShel If this condition is detected PowerShell Core: 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. 2. generates local proxy module/commands using `WinPSCompatSession` remoting session and code of `Import-Module -PSSession` cmdlet; - 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).
+ 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). + Loading a module into `WinPSCompatSession` can be forced regardless of module path or value of `CompatiblePSEditions` manifest property using `-UseWindowsPowerShell` parameter of `Import-Module`.
New functionality should also be supported during module autoload / command discovery.
Loading of modules into `WinPSCompat` should be tracked in telemetry separately from loading other modules so `TelemetryType.WinCompatModuleLoad` needs to be added. From 012e3425de7d281c25c648173ef8cd0a4056a19f Mon Sep 17 00:00:00 2001 From: Andrew Menagarishvili Date: Mon, 18 Nov 2019 09:08:48 -0800 Subject: [PATCH 19/22] Added module blacklist --- ...ting-Windows-PowerShell-modules-in-PowerShell-Core.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index 40be3655..d76b64bd 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -65,6 +65,15 @@ Redirected process streams transport (same one used by PS jobs) is to be used fo A new WindowsPS-specific parameter set will be added to New-PSSession: `New-PSSession -UseWindowsPowerShell [-Name ]` 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. +### Module blacklist + +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. +Some modules don't work well with de/serialized objects (e.g. pipeline cmdlet combinations of 'Hyper-V' module);
+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.
+For such cases it is necessary to implement a module blacklist.
+For modules in the blacklist this feature will not engage (and current behavior of generating 'PSEditionNotSupported' error will be maintained).
+Module blacklist defined using a 'WindowsPowerShellCompatibilityModuleBlacklist' setting in 'powershell.config.json' so that user can change it when needed. + ### Lifetime of 'compatibility' Windows PowerShell process and module 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: From 80e55e63eff95bcc0c15a69707b7ac203a090c80 Mon Sep 17 00:00:00 2001 From: Joey Aiello Date: Mon, 9 Dec 2019 12:34:27 -0800 Subject: [PATCH 20/22] Change "blacklist" to "deny list" --- ...rting-Windows-PowerShell-modules-in-PowerShell-Core.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index d76b64bd..586ffc98 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -65,14 +65,14 @@ Redirected process streams transport (same one used by PS jobs) is to be used fo A new WindowsPS-specific parameter set will be added to New-PSSession: `New-PSSession -UseWindowsPowerShell [-Name ]` 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. -### Module blacklist +### Module deny list 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. Some modules don't work well with de/serialized objects (e.g. pipeline cmdlet combinations of 'Hyper-V' module);
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.
-For such cases it is necessary to implement a module blacklist.
-For modules in the blacklist this feature will not engage (and current behavior of generating 'PSEditionNotSupported' error will be maintained).
-Module blacklist defined using a 'WindowsPowerShellCompatibilityModuleBlacklist' setting in 'powershell.config.json' so that user can change it when needed. +For such cases it is necessary to implement a module deny list.
+For modules in the deny list this feature will not engage (and current behavior of generating 'PSEditionNotSupported' error will be maintained).
+Module deny list defined using a 'WindowsPowerShellCompatibilityModuleDenyList' setting in 'powershell.config.json' so that user can change it when needed. ### Lifetime of 'compatibility' Windows PowerShell process and module From 60382e16a7577b80e418ee90ffb3ac933d6158d0 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 5 Feb 2020 16:22:41 -0800 Subject: [PATCH 21/22] Update 2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md Co-Authored-By: Joey Aiello --- ...-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index 586ffc98..0629bc08 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -74,6 +74,8 @@ For such cases it is necessary to implement a module deny list.
For modules in the deny list this feature will not engage (and current behavior of generating 'PSEditionNotSupported' error will be maintained).
Module deny list defined using a 'WindowsPowerShellCompatibilityModuleDenyList' setting in 'powershell.config.json' so that user can change it when needed. +Going forward, we will continue to update this list if any modules are discovered to have problems operating in this compatibility layer. + ### Lifetime of 'compatibility' Windows PowerShell process and module 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: @@ -103,4 +105,3 @@ With PS Remoting objects returned from remote 'compatibility' side are not actua + requires setup + not the best transport performance-wise - Introduces additional cmdlets to work with 'WindowsPS-only' modules, i.e. does not have transparent user experience. - From 2cb3f3537851d0bd27e07bda48f8915558a6e5cd Mon Sep 17 00:00:00 2001 From: Joey Aiello Date: Wed, 19 Feb 2020 15:16:00 -0800 Subject: [PATCH 22/22] Prep RFC0050 for merging (WinPS Compat Layer) Unanimous consensus to accept from the Committee --- ...Importing-Windows-PowerShell-modules-in-PowerShell-Core.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename 2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md => 5-Final/RFC0050-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md (98%) diff --git a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md b/5-Final/RFC0050-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md similarity index 98% rename from 2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md rename to 5-Final/RFC0050-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md index 0629bc08..0f593144 100644 --- a/2-Draft-Accepted/RFCNNN-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md +++ b/5-Final/RFC0050-Importing-Windows-PowerShell-modules-in-PowerShell-Core.md @@ -1,7 +1,7 @@ --- -RFC: +RFC: 0050 Author: Andrew Menagarishvili -Status: Draft +Status: Final SupercededBy: Version: 0.1 Area: Language