@@ -400,8 +400,14 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
400
400
}
401
401
402
402
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.
405
411
if ( variableContainerReferenceId == localScopeVariables . Id )
406
412
{
407
413
scope = VariableContainerDetails . LocalScopeName ;
@@ -414,11 +420,6 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
414
420
{
415
421
scope = VariableContainerDetails . GlobalScopeName ;
416
422
}
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
- }
422
423
423
424
// Now that we have the scope, get the associated PSVariable object for the variable to be set.
424
425
var getVariableCommand = new PSCommand ( )
@@ -456,22 +457,25 @@ public async Task<string> SetVariableAsync(int variableContainerReferenceId, str
456
457
457
458
if ( argTypeConverterAttr is not null )
458
459
{
460
+ // PSVariable *is* strongly typed, so we have to convert it.
459
461
_logger . LogTrace ( $ "Setting variable '{ name } ' using conversion to value: { expressionResult ?? "<null>" } ") ;
460
462
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" ) ,
474
471
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 ) ;
475
479
}
476
480
else
477
481
{
@@ -641,7 +645,7 @@ private Task<VariableContainerDetails> FetchVariableContainerAsync(string scope)
641
645
642
646
private async Task < VariableContainerDetails > FetchVariableContainerAsync ( string scope , bool autoVarsOnly )
643
647
{
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 ) ;
645
649
646
650
var scopeVariableContainer = new VariableContainerDetails ( nextVariableId ++ , "Scope: " + scope ) ;
647
651
variables . Add ( scopeVariableContainer ) ;
0 commit comments