PowerShell / WindowsCompatibility

Module that allows Windows PowerShell Modules to be used from PSCore6
Other
137 stars 33 forks source link

Error when importing a windows module in $profile using 1.0.0.rc1 #56

Closed KaylorDave closed 5 years ago

KaylorDave commented 5 years ago

When importing a module inside of the PowerShell profile, the WindowsCompatibility module is throwing an error regarding Set-Location and $PSBoundParameters. The imported module still works correctly, but this slows down profile loading significantly (and adds red to my PowerShell sessions immediately).

pwsh version info-

PS C:\Users\kaylorw> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.1.0
PSEdition                      Core
GitCommitId                    6.1.0
OS                             Microsoft Windows 10.0.17763
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Contents of $profile file- Import-WinModule -Name microsoft.powershell.management

Error text received-

Set-Location : The variable '$PSBoundParameters' cannot be retrieved because it has not been set.
+ CategoryInfo          : InvalidOperation: (PSBoundParameters:String) [Set-Location], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined,Microsoft.PowerShell.Commands.SetLocationCommand

Full error context-

ErrorRecord                 : The variable '$PSBoundParameters' cannot be retrieved because it has not been set.
WasThrownFromThrowStatement : False
Message                     : The variable '$PSBoundParameters' cannot be retrieved because it has not been set.
Data                        : {}
InnerException              : System.Management.Automation.RuntimeException: The variable '$PSBoundParameters' cannot
                              be retrieved because it has not been set.
                                 at
                              System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext
                              funcContext, Exception exception)
                                 at
                              System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame
                              frame)
                                 at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(Interp
                              retedFrame frame)
                                 at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(Interp
                              retedFrame frame)
                                 at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
                                 at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
                                 at
                              System.Management.Automation.ScriptBlock.InvokeWithPipeImpl(ScriptBlockClauseToInvoke
                              clauseToInvoke, Boolean createLocalScope, Dictionary`2 functionsToDefine, List`1
                              variablesToDefine, ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder,
                              Object input, Object scriptThis, Pipe outputPipe, InvocationInfo invocationInfo,
                              Object[] args)
                                 at
                              System.Management.Automation.ScriptBlock.<>c__DisplayClass57_0.<InvokeWithPipe>b__0()
                                 at System.Management.Automation.Runspaces.RunspaceBase.RunActionIfNoRunningPipelinesWi
                              thThreadCheck(Action action)
                                 at System.Management.Automation.ScriptBlock.InvokeWithPipe(Boolean useLocalScope,
                              ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object
                              scriptThis, Pipe outputPipe, InvocationInfo invocationInfo, Boolean
                              propagateAllExceptionsToTop, List`1 variablesToDefine, Dictionary`2 functionsToDefine,
                              Object[] args)
                                 at System.Management.Automation.ScriptBlock.InvokeAsDelegateHelper(Object
                              dollarUnder, Object dollarThis, Object[] args)
                                 at lambda_method(Closure , Object , LocationChangedEventArgs )
                                 at System.Management.Automation.SessionStateInternal.SetLocation(String path,
                              CmdletProviderContext context)
                                 at System.Management.Automation.PathIntrinsics.SetLocation(String path,
                              CmdletProviderContext context)
                                 at Microsoft.PowerShell.Commands.SetLocationCommand.ProcessRecord()
                                 at System.Management.Automation.Cmdlet.DoProcessRecord()
                                 at System.Management.Automation.CommandProcessor.ProcessRecord()
TargetSite                  : System.Collections.ObjectModel.Collection`1[System.Management.Automation.PSObject]
                              Invoke(System.Collections.IEnumerable)
StackTrace                  :    at System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable input)
                                 at System.Management.Automation.Runspaces.Pipeline.Invoke()
                                 at Microsoft.PowerShell.Executor.ExecuteCommandHelper(Pipeline tempPipeline,
                              Exception& exceptionThrown, ExecutionOptions options)
HelpLink                    :
Source                      : System.Management.Automation
HResult                     : -2146233087
BrucePay commented 5 years ago

@KaylorDave WinModule uses implicit remoting to talk to a Windows PowerShell session but before it can do that, it has to create the remote session and that takes significant time since it's starting another instance of PowerShell. Unfortunately there isn't much more we can do to speed that up.

KaylorDave commented 5 years ago

@BrucePay thanks for getting back! Sorry I should have been more specific. I meant it is slowing things down in comparison to the previous version of WinModule. I do not encounter the error or slowdown when using the older version. Only this pre-release candidate. Happy to provide any additional information I can to resolve this, I've currently just reverted to version 0.0.1.

KaylorDave commented 5 years ago

To give some specific data on the difference in experience, I've replaced the contents of my profile with just 2 lines and run some tests with the only difference in profile being the 'RequiredVersion' of WindowsCompatibility (WinModule) being imported-

Import-Module -Name WindowsCompatibility -RequiredVersion 0.0.1
Import-WinModule -Name microsoft.powershell.management

New pwsh window with 0.0.1 loading-

PowerShell 6.1.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

Loading personal and system profiles took 3832ms.

New pwsh window with 1.0.0 loading-

PowerShell 6.1.0
Copyright (c) Microsoft Corporation. All rights reserved.

https://aka.ms/pscore6-docs
Type 'help' to get help.

Loading personal and system profiles took 4817ms.
Set-Location : The variable '$PSBoundParameters' cannot be retrieved because it has not been set.
+ CategoryInfo          : InvalidOperation: (PSBoundParameters:String) [Set-Location], RuntimeException
+ FullyQualifiedErrorId : VariableIsUndefined,Microsoft.PowerShell.Commands.SetLocationCommand
KaylorDave commented 5 years ago

I've done some debugging, but unfortunately I can't seem to get the error to happen when not during profile load time so I haven't been able to trace the exact line the error is occurring at. However, I have been able to narrow it down based on verbose output to be inside the module's psm1 file and located at either line 537 or lines 539-541 (all one command).

The error is for sure in this code block though-

if ($noClobberNames)
        {
            $importModuleParameters.PassThru = $true
            foreach ($name in $noClobberNames)
            {
                $module = Import-Module -Name $name -NoClobber @importModuleParameters
                # Hack using private reflection to keep the proxy module from shadowing the real module.
                $null = [PSModuleInfo].
                    GetMethod('SetName',[System.Reflection.BindingFlags]'Instance, NonPublic').
                        Invoke($module, @($module.Name + '.WinModule'))
                if($PassThru.IsPresent)
                {
                    $module
                }
            }
        }
BrucePay commented 5 years ago

I haven't been able to repro this but i believe the problem is line 101:

[PSSession] $session = Initialize-WinSession @PSBoundParameters -PassThru

I'll update the code to use explicit parameters. That should hopefully fix your problem.

KaylorDave commented 5 years ago

This fixed it, thanks!