@@ -668,6 +668,11 @@ private async Task<VariableContainerDetails> FetchVariableContainerAsync(string
668668            } 
669669            catch  ( CmdletInvocationException  ex ) 
670670            { 
671+                 // It's possible to be asked to run `Get-Variable -Scope N` where N is a number that 
672+                 // exceeds the available scopes. In this case, the command throws this exception, 
673+                 // but there's nothing we can do about it, nor can we know the number of scopes that 
674+                 // exist, and we shouldn't crash the debugger, so we just return no results instead. 
675+                 // All other exceptions should be thrown again. 
671676                if  ( ! ex . ErrorRecord . CategoryInfo . Reason . Equals ( "PSArgumentOutOfRangeException" ) ) 
672677                { 
673678                    throw ; 
@@ -757,6 +762,8 @@ private bool AddToAutoVariables(PSObject psvariable, string scope)
757762            if  ( ( ( variableScope  &  constantAllScope )  ==  constantAllScope ) 
758763                ||  ( ( variableScope  &  readonlyAllScope )  ==  readonlyAllScope ) ) 
759764            { 
765+                 // The constructor we are using here does not automatically add the dollar prefix, 
766+                 // so we do it manually. 
760767                string  prefixedVariableName  =  VariableDetails . DollarPrefix  +  variableName ; 
761768                if  ( globalScopeVariables . Children . ContainsKey ( prefixedVariableName ) ) 
762769                { 
@@ -769,30 +776,27 @@ private bool AddToAutoVariables(PSObject psvariable, string scope)
769776
770777        private  async  Task  FetchStackFramesAsync ( string  scriptNameOverride ) 
771778        { 
772-             PSCommand  psCommand  =  new  PSCommand ( ) ; 
773-             // The serialization depth to retrieve variables from remote runspaces. 
774-             const  int  serializationDepth  =  3 ; 
775- 
776779            // This glorious hack ensures that Get-PSCallStack returns a list of CallStackFrame 
777780            // objects (or "deserialized" CallStackFrames) when attached to a runspace in another 
778-             // process.  Without the intermediate variable Get-PSCallStack inexplicably returns 
779-             // an array of strings containing the formatted output of the CallStackFrame list. 
780-             string  callStackVarName  =  $ "$global:{ PsesGlobalVariableNamePrefix } CallStack"; 
781- 
782-             string  getPSCallStack  =  $ "Get-PSCallStack | ForEach-Object {{ [void]{ callStackVarName } .add(@($PSItem,$PSItem.GetFrameVariables())) }}"; 
783- 
784-             // If we're attached to a remote runspace, we need to serialize the callstack prior to transport 
785-             // because the default depth is too shallow 
781+             // process. Without the intermediate variable Get-PSCallStack inexplicably returns an 
782+             // array of strings containing the formatted output of the CallStackFrame list. So we 
783+             // run a script that builds the list of CallStackFrames and their variables. 
784+             const  string  callStackVarName  =  $ "$global:{ PsesGlobalVariableNamePrefix } CallStack"; 
785+             const  string  getPSCallStack  =  $ "Get-PSCallStack | ForEach-Object {{ [void]{ callStackVarName } .Add(@($PSItem, $PSItem.GetFrameVariables())) }}"; 
786+ 
787+             // If we're attached to a remote runspace, we need to serialize the list prior to 
788+             // transport because the default depth is too shallow. From testing, we determined the 
789+             // correct depth is 3. The script always calls `Get-PSCallStack`. On a local machine, we 
790+             // just return its results. On a remote machine we serialize it first and then later 
791+             // deserialize it. 
786792            bool  isOnRemoteMachine  =  _psesHost . CurrentRunspace . IsOnRemoteMachine ; 
787793            string  returnSerializedIfOnRemoteMachine  =  isOnRemoteMachine 
788-                 ?  $ "[Management.Automation.PSSerializer]::Serialize({ callStackVarName } , { serializationDepth } )"
794+                 ?  $ "[Management.Automation.PSSerializer]::Serialize({ callStackVarName } , 3 )"
789795                :  callStackVarName ; 
790796
791-             // We have to deal with a shallow serialization depth with ExecutePSCommandAsync as well, hence the serializer to get full var information 
792-             psCommand . AddScript ( $ "[Collections.ArrayList]{ callStackVarName }  = @(); { getPSCallStack } ; { returnSerializedIfOnRemoteMachine } ") ; 
793- 
794- 
795-             // PSObject is used here instead of the specific type because we get deserialized objects from remote sessions and want a common interface 
797+             // PSObject is used here instead of the specific type because we get deserialized 
798+             // objects from remote sessions and want a common interface. 
799+             var  psCommand  =  new  PSCommand ( ) . AddScript ( $ "[Collections.ArrayList]{ callStackVarName }  = @(); { getPSCallStack } ; { returnSerializedIfOnRemoteMachine } ") ; 
796800            IReadOnlyList < PSObject >  results  =  await  _executionService . ExecutePSCommandAsync < PSObject > ( psCommand ,  CancellationToken . None ) . ConfigureAwait ( false ) ; 
797801
798802            IEnumerable  callStack  =  isOnRemoteMachine 
@@ -816,11 +820,13 @@ private async Task FetchStackFramesAsync(string scriptNameOverride)
816820
817821                foreach  ( DictionaryEntry  entry  in  callStackVariables ) 
818822                { 
819-                     // TODO: This should be deduplicated into a new function for the other variable handling as well  
823+                     // TODO: This should be deduplicated into a new function.  
820824                    object  psVarValue  =  isOnRemoteMachine 
821825                        ?  ( entry . Value  as  PSObject ) . Properties [ "Value" ] . Value 
822826                        :  ( entry . Value  as  PSVariable ) . Value ; 
823-                     // The constructor we are using here does not automatically add the dollar prefix 
827+ 
828+                     // The constructor we are using here does not automatically add the dollar 
829+                     // prefix, so we do it manually. 
824830                    string  psVarName  =  VariableDetails . DollarPrefix  +  entry . Key . ToString ( ) ; 
825831                    var  variableDetails  =  new  VariableDetails ( psVarName ,  psVarValue )  {  Id  =  nextVariableId ++  } ; 
826832                    variables . Add ( variableDetails ) ; 
0 commit comments