@@ -400,8 +400,14 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
400400 }
401401
402402 VariableDetailsBase variable = variableContainer . Children [ name ] ;
403- // Determine scope in which the variable lives so we can pass it to `Get-Variable -Scope`.
404- string scope = null ; // TODO: Can this use a fancy pattern matcher?
403+
404+ // Determine scope in which the variable lives so we can pass it to `Get-Variable
405+ // -Scope`. The default is scope 0 which is safe because if a user is able to see a
406+ // variable in the debugger and so change it through this interface, it's either in the
407+ // top-most scope or in one of the following named scopes. The default scope is most
408+ // likely in the case of changing from the "auto variables" container.
409+ string scope = "0" ;
410+ // NOTE: This can't use a switch because the IDs aren't constant.
405411 if ( variableContainerReferenceId == localScopeVariables . Id )
406412 {
407413 scope = VariableContainerDetails . LocalScopeName ;
@@ -414,11 +420,6 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
414420 {
415421 scope = VariableContainerDetails . GlobalScopeName ;
416422 }
417- else
418- {
419- // Hmm, this would be unexpected. No scope means do not pass GO, do not collect $200.
420- throw new Exception ( "Could not find the scope for this variable." ) ;
421- }
422423
423424 // Now that we have the scope, get the associated PSVariable object for the variable to be set.
424425 var getVariableCommand = new PSCommand ( )
@@ -456,22 +457,25 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
456457
457458 if ( argTypeConverterAttr is not null )
458459 {
460+ // PSVariable *is* strongly typed, so we have to convert it.
459461 _logger . LogTrace ( $ "Setting variable '{ name } ' using conversion to value: { expressionResult ?? "<null>" } ") ;
460462
461- // TODO: This is throwing a 'PSInvalidOperationException' thus causing
462- // 'DebuggerSetsVariablesWithConversion' to fail.
463- psVariable . Value = await _executionService . ExecuteDelegateAsync (
464- "PS debugger argument converter" ,
465- ExecutionOptions . Default ,
466- ( pwsh , _ ) =>
467- {
468- var engineIntrinsics = ( EngineIntrinsics ) pwsh . Runspace . SessionStateProxy . GetVariable ( "ExecutionContext" ) ;
469-
470- // TODO: This is almost (but not quite) the same as LanguagePrimitives.Convert(), which does not require the pipeline thread.
471- // We should investigate changing it.
472- return argTypeConverterAttr . Transform ( engineIntrinsics , expressionResult ) ;
473- } ,
463+ // NOTE: We use 'Get-Variable' here instead of 'SessionStateProxy.GetVariable()'
464+ // because we already have a pipeline running (the debugger) and the latter cannot
465+ // run concurrently (threw 'NoSessionStateProxyWhenPipelineInProgress').
466+ IReadOnlyList < EngineIntrinsics > results = await _executionService . ExecutePSCommandAsync < EngineIntrinsics > (
467+ new PSCommand ( )
468+ . AddCommand ( @"Microsoft.PowerShell.Utility\Get-Variable" )
469+ . AddParameter ( "Name" , "ExecutionContext" )
470+ . AddParameter ( "ValueOnly" ) ,
474471 CancellationToken . None ) . ConfigureAwait ( false ) ;
472+ EngineIntrinsics engineIntrinsics = results . Count > 0
473+ ? results [ 0 ]
474+ : throw new Exception ( "Couldn't get EngineIntrinsics!" ) ;
475+
476+ // TODO: This is almost (but not quite) the same as 'LanguagePrimitives.Convert()',
477+ // which does not require the pipeline thread. We should investigate changing it.
478+ psVariable . Value = argTypeConverterAttr . Transform ( engineIntrinsics , expressionResult ) ;
475479 }
476480 else
477481 {
@@ -641,7 +645,7 @@ private Task<VariableContainerDetails> FetchVariableContainerAsync(string scope)
641645
642646 private async Task < VariableContainerDetails > FetchVariableContainerAsync ( string scope , bool autoVarsOnly )
643647 {
644- PSCommand psCommand = new PSCommand ( ) . AddCommand ( " Get-Variable") . AddParameter ( "Scope" , scope ) ;
648+ PSCommand psCommand = new PSCommand ( ) . AddCommand ( @"Microsoft.PowerShell.Utility\ Get-Variable") . AddParameter ( "Scope" , scope ) ;
645649
646650 var scopeVariableContainer = new VariableContainerDetails ( nextVariableId ++ , "Scope: " + scope ) ;
647651 variables . Add ( scopeVariableContainer ) ;
0 commit comments