protected async Task HandleEvaluateRequest( DebugAdapterMessages.EvaluateRequestArguments evaluateParams, EditorSession editorSession, RequestContext <DebugAdapterMessages.EvaluateResponseBody, object> requestContext) { VariableDetails result = await editorSession.DebugService.EvaluateExpression( evaluateParams.Expression, evaluateParams.FrameId); string valueString = null; int variableId = 0; if (result != null) { valueString = result.ValueString; variableId = result.IsExpandable ? result.Id : 0; } await requestContext.SendResult( new DebugAdapterMessages.EvaluateResponseBody { Result = valueString, VariablesReference = variableId }); }
protected async Task HandleEvaluateRequest( EvaluateRequestArguments evaluateParams, RequestContext <EvaluateResponseBody> requestContext) { string valueString = null; int variableId = 0; bool isFromRepl = string.Equals( evaluateParams.Context, "repl", StringComparison.CurrentCultureIgnoreCase); if (isFromRepl) { // Check for special commands if (string.Equals("!ctrlc", evaluateParams.Expression, StringComparison.CurrentCultureIgnoreCase)) { editorSession.PowerShellContext.AbortExecution(); } else if (string.Equals("!break", evaluateParams.Expression, StringComparison.CurrentCultureIgnoreCase)) { editorSession.DebugService.Break(); } else { // Send the input through the console service editorSession.ConsoleService.ExecuteCommand( evaluateParams.Expression, false); } } else { VariableDetails result = await editorSession.DebugService.EvaluateExpression( evaluateParams.Expression, evaluateParams.FrameId, isFromRepl); if (result != null) { valueString = result.ValueString; variableId = result.IsExpandable ? result.Id : 0; } } await requestContext.SendResult( new EvaluateResponseBody { Result = valueString, VariablesReference = variableId }); }
private VariableDetails GetDetails(int localIndex) { var detailsItem = this.details.GetValueOrDefault(localIndex); if (detailsItem == null) { detailsItem = new VariableDetails(); this.details.Add(localIndex, detailsItem); } return detailsItem; }
public static Variable Create(VariableDetails variable) { return(new Variable { Name = variable.Name, Value = variable.ValueString ?? string.Empty, VariablesReference = variable.IsExpandable ? variable.Id : 0 }); }
protected async Task HandleEvaluateRequest( EvaluateRequestArguments evaluateParams, RequestContext <EvaluateResponseBody> requestContext) { string valueString = null; int variableId = 0; bool isFromRepl = string.Equals( evaluateParams.Context, "repl", StringComparison.CurrentCultureIgnoreCase); if (isFromRepl) { // TODO: Do we send the input through the command handler? // Send the input through the console service var notAwaited = this.editorSession .PowerShellContext .ExecuteScriptString(evaluateParams.Expression, false, true) .ConfigureAwait(false); } else { VariableDetails result = null; // VS Code might send this request after the debugger // has been resumed, return an empty result in this case. if (editorSession.PowerShellContext.IsDebuggerStopped) { result = await editorSession.DebugService.EvaluateExpression( evaluateParams.Expression, evaluateParams.FrameId, isFromRepl); } if (result != null) { valueString = result.ValueString; variableId = result.IsExpandable ? result.Id : 0; } } await requestContext.SendResult( new EvaluateResponseBody { Result = valueString, VariablesReference = variableId }); }
public static Variable Create(VariableDetails variable) { return new Variable { Name = variable.Name, Value = variable.ValueString ?? string.Empty, VariablesReference = variable.IsExpandable ? variable.Id : 0 }; }
private VariableDetails GetDetails(int localIndex) { var detailsItem = this.details.GetValueOrDefault(localIndex); if (detailsItem == null) { detailsItem = new VariableDetails(); this.details.Add(localIndex, detailsItem); } return(detailsItem); }
private async Task <VariableContainerDetails> FetchVariableContainerAsync( string scope, VariableContainerDetails autoVariables) { PSCommand psCommand = new PSCommand(); psCommand.AddCommand("Get-Variable"); psCommand.AddParameter("Scope", scope); var scopeVariableContainer = new VariableContainerDetails(this.nextVariableId++, "Scope: " + scope); this.variables.Add(scopeVariableContainer); var results = await this.powerShellContext.ExecuteCommandAsync <PSObject>(psCommand, sendErrorToHost : false).ConfigureAwait(false); if (results != null) { foreach (PSObject psVariableObject in results) { var variableDetails = new VariableDetails(psVariableObject) { Id = this.nextVariableId++ }; this.variables.Add(variableDetails); scopeVariableContainer.Children.Add(variableDetails.Name, variableDetails); if ((autoVariables != null) && AddToAutoVariables(psVariableObject, scope)) { autoVariables.Children.Add(variableDetails.Name, variableDetails); } } } return(scopeVariableContainer); }
public List <VariableDetails> GetVariableDetails(VariableInfo info) { if (info == null) { return(null); } ; var list = new List <VariableDetails>(); if (_service.Cpus.ContainsKey(info.CpuName)) { var cpu = _service.Cpus[info.CpuName]; foreach (var variable in info.Variables) { if (cpu.Variables.ContainsKey(variable)) { var value = ConvertVariableValue(cpu.Variables[variable].Value); var details = new VariableDetails(); details.Name = cpu.Variables[variable].Name; details.CpuName = info.CpuName; details.Value = value; details.IsConnected = cpu.Variables[variable].IsConnected; details.HasError = cpu.Variables[variable].HasError; details.ErrorCode = cpu.Variables[variable].ErrorCode.ToString(); details.ErrorText = cpu.Variables[variable].ErrorText; list.Add(details); } } } return(list); }
public object GetVariableValue(string guid, string variableName) { if (!IsLoggedInUserAuthorized) { return(string.Empty); } var sessionExists = ScriptSessionManager.SessionExists(guid); if (!sessionExists) { return("<div class='undefinedVariableType'>Session not found</div>" + "<div class='variableLine'>A script needs to be executed in the session<br/>before the variable value can be inspected.</div>"); } var session = ScriptSessionManager.GetSession(guid); try { variableName = variableName.TrimStart('$'); var debugVariable = session.GetDebugVariable(variableName); if (debugVariable == null) { return("<div class='undefinedVariableType'>undefined</div>" + $"<div class='variableLine'><span class='varName'>${variableName}</span> : <span class='varValue'>$null</span></div>"); } var defaultProps = new string[0]; if (debugVariable is PSObject) { var script = $"${variableName}.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames"; session.Output.SilenceOutput = true; try { if (session.TryInvokeInRunningSession(script, out List <object> results) && results != null) { defaultProps = session.IsRunning ? (session.Output.SilencedOutput?.ToString() .Split('\n') .Select(line => line.Trim()) .ToArray() ?? new string[0]) : results.Cast <string>().ToArray(); session.Output.SilencedOutput?.Clear(); } } finally { session.Output.SilenceOutput = false; } } var variable = debugVariable.BaseObject(); if (variable is PSCustomObject) { variable = debugVariable; } var details = new VariableDetails("$" + variableName, variable); var varValue = $"<div class='variableType'>{variable.GetType().FullName}</div>"; varValue += $"<div class='variableLine'><span class='varName'>${variableName}</span> : <span class='varValue'>{details.HtmlEncodedValueString}</span></div>"; if (!details.IsExpandable) { return(varValue); } // sort only if the object is not an array otherwise the indexes will get scrambled. var children = details.ShowDotNetProperties ? details.GetChildren().OrderBy(d => d.Name).ToArray() : details.GetChildren(); foreach (var child in children) { if (!child.IsExpandable || defaultProps.Contains(child.Name, StringComparer.OrdinalIgnoreCase) || ImportantProperties.Contains(child.Name, StringComparer.OrdinalIgnoreCase)) { varValue += $"<span class='varChild'><span class='childName'>{child.Name}</span> : <span class='childValue'>{child.HtmlEncodedValueString}</span></span>"; } else { if (details.ShowDotNetProperties) { continue; } varValue += $"<span class='varChild'><span class='childName'>{child.Name}</span> : <span class='childValue'>{{"; foreach (var subChild in child.GetChildren()) { if (!subChild.IsExpandable) { varValue += $"<span class='childName'>{subChild.Name}</span> : {subChild.HtmlEncodedValueString}, "; } } varValue = varValue.TrimEnd(' ', ','); varValue += "}</span></span>"; } } if (details.MaxArrayParseSizeExceeded) { varValue += $"<span class='varChild'><span class='varName'>... first {VariableDetails.MaxArrayParseSize} items shown.</span></span>"; } return(varValue); } catch (Exception ex) { return(ex.Message); } }
/// <summary> /// Sets the specified variable by container variableReferenceId and variable name to the /// specified new value. If the variable cannot be set or converted to that value this /// method will throw InvalidPowerShellExpressionException, ArgumentTransformationMetadataException, or /// SessionStateUnauthorizedAccessException. /// </summary> /// <param name="variableContainerReferenceId">The container (Autos, Local, Script, Global) that holds the variable.</param> /// <param name="name">The name of the variable prefixed with $.</param> /// <param name="value">The new string value. This value must not be null. If you want to set the variable to $null /// pass in the string "$null".</param> /// <returns>The string representation of the value the variable was set to.</returns> public async Task <string> SetVariableAsync(int variableContainerReferenceId, string name, string value) { Validate.IsNotNull(nameof(name), name); Validate.IsNotNull(nameof(value), value); this.logger.LogTrace($"SetVariableRequest for '{name}' to value string (pre-quote processing): '{value}'"); // An empty or whitespace only value is not a valid expression for SetVariable. if (value.Trim().Length == 0) { throw new InvalidPowerShellExpressionException("Expected an expression."); } // Evaluate the expression to get back a PowerShell object from the expression string. PSCommand psCommand = new PSCommand(); psCommand.AddScript(value); var errorMessages = new StringBuilder(); var results = await this.powerShellContext.ExecuteCommandAsync <object>( psCommand, errorMessages, false, false).ConfigureAwait(false); // Check if PowerShell's evaluation of the expression resulted in an error. object psobject = results.FirstOrDefault(); if ((psobject == null) && (errorMessages.Length > 0)) { throw new InvalidPowerShellExpressionException(errorMessages.ToString()); } // If PowerShellContext.ExecuteCommand returns an ErrorRecord as output, the expression failed evaluation. // Ideally we would have a separate means from communicating error records apart from normal output. if (psobject is ErrorRecord errorRecord) { throw new InvalidPowerShellExpressionException(errorRecord.ToString()); } // OK, now we have a PS object from the supplied value string (expression) to assign to a variable. // Get the variable referenced by variableContainerReferenceId and variable name. VariableContainerDetails variableContainer = null; await this.debugInfoHandle.WaitAsync().ConfigureAwait(false); try { variableContainer = (VariableContainerDetails)this.variables[variableContainerReferenceId]; } finally { this.debugInfoHandle.Release(); } VariableDetailsBase variable = variableContainer.Children[name]; // Determine scope in which the variable lives. This is required later for the call to Get-Variable -Scope. string scope = null; if (variableContainerReferenceId == this.scriptScopeVariables.Id) { scope = "Script"; } else if (variableContainerReferenceId == this.globalScopeVariables.Id) { scope = "Global"; } else { // Determine which stackframe's local scope the variable is in. StackFrameDetails[] stackFrames = await this.GetStackFramesAsync().ConfigureAwait(false); for (int i = 0; i < stackFrames.Length; i++) { var stackFrame = stackFrames[i]; if (stackFrame.LocalVariables.ContainsVariable(variable.Id)) { scope = i.ToString(); break; } } } if (scope == null) { // Hmm, this would be unexpected. No scope means do not pass GO, do not collect $200. throw new Exception("Could not find the scope for this variable."); } // Now that we have the scope, get the associated PSVariable object for the variable to be set. psCommand.Commands.Clear(); psCommand = new PSCommand(); psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Get-Variable"); psCommand.AddParameter("Name", name.TrimStart('$')); psCommand.AddParameter("Scope", scope); IEnumerable <PSVariable> result = await this.powerShellContext.ExecuteCommandAsync <PSVariable>(psCommand, sendErrorToHost : false).ConfigureAwait(false); PSVariable psVariable = result.FirstOrDefault(); if (psVariable == null) { throw new Exception($"Failed to retrieve PSVariable object for '{name}' from scope '{scope}'."); } // We have the PSVariable object for the variable the user wants to set and an object to assign to that variable. // The last step is to determine whether the PSVariable is "strongly typed" which may require a conversion. // If it is not strongly typed, we simply assign the object directly to the PSVariable potentially changing its type. // Turns out ArgumentTypeConverterAttribute is not public. So we call the attribute through it's base class - // ArgumentTransformationAttribute. var argTypeConverterAttr = psVariable.Attributes .OfType <ArgumentTransformationAttribute>() .FirstOrDefault(a => a.GetType().Name.Equals("ArgumentTypeConverterAttribute")); if (argTypeConverterAttr != null) { // PSVariable is strongly typed. Need to apply the conversion/transform to the new value. psCommand.Commands.Clear(); psCommand = new PSCommand(); psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Get-Variable"); psCommand.AddParameter("Name", "ExecutionContext"); psCommand.AddParameter("ValueOnly"); errorMessages.Clear(); var getExecContextResults = await this.powerShellContext.ExecuteCommandAsync <object>( psCommand, errorMessages, sendErrorToHost : false).ConfigureAwait(false); EngineIntrinsics executionContext = getExecContextResults.OfType <EngineIntrinsics>().FirstOrDefault(); var msg = $"Setting variable '{name}' using conversion to value: {psobject ?? "<null>"}"; this.logger.LogTrace(msg); psVariable.Value = argTypeConverterAttr.Transform(executionContext, psobject); } else { // PSVariable is *not* strongly typed. In this case, whack the old value with the new value. var msg = $"Setting variable '{name}' directly to value: {psobject ?? "<null>"} - previous type was {psVariable.Value?.GetType().Name ?? "<unknown>"}"; this.logger.LogTrace(msg); psVariable.Value = psobject; } // Use the VariableDetails.ValueString functionality to get the string representation for client debugger. // This makes the returned string consistent with the strings normally displayed for variables in the debugger. var tempVariable = new VariableDetails(psVariable); this.logger.LogTrace($"Set variable '{name}' to: {tempVariable.ValueString ?? "<null>"}"); return(tempVariable.ValueString); }
public object GetVariableValue(string guid, string variableName) { var sessionExists = ScriptSessionManager.SessionExists(guid); if (sessionExists) { var session = ScriptSessionManager.GetSession(guid); try { variableName = variableName.TrimStart('$'); var debugVariable = session.GetDebugVariable(variableName); if (debugVariable == null) { return($"<div class='undefinedVariableType'>undefined</div>" + $"<div class='variableLine'><span class='varName'>${variableName}</span> : <span class='varValue'>$null</span></div>"); } var defaultProps = new List <string>(); if (debugVariable is PSObject && !session.IsRunning) { var script = $"${variableName}.PSStandardMembers.DefaultDisplayPropertySet.ReferencedPropertyNames"; List <object> results; if (session.TryInvokeInRunningSession(script, out results) && results != null) { defaultProps = results.Cast <string>().ToList(); } } var variable = debugVariable.BaseObject(); if (variable is PSCustomObject) { variable = debugVariable; } VariableDetails details = new VariableDetails("$" + variableName, variable); var varValue = $"<div class='variableType'>{variable.GetType().FullName}</div>"; varValue += $"<div class='variableLine'><span class='varName'>${variableName}</span> : <span class='varValue'>{details.HtmlEncodedValueString}</span></div>"; if (details.IsExpandable) { foreach (var child in details.GetChildren().OrderBy(d => d.Name)) { if (!child.IsExpandable || defaultProps.Contains(child.Name, StringComparer.OrdinalIgnoreCase) || ImportantProperties.Contains(child.Name, StringComparer.OrdinalIgnoreCase)) { varValue += $"<span class='varChild'><span class='childName'>{child.Name}</span> : <span class='childValue'>{child.HtmlEncodedValueString}</span></span>"; } else { if (details.ShowDotNetProperties) { continue; } varValue += $"<span class='varChild'><span class='childName'>{child.Name}</span> : <span class='childValue'>{{"; foreach (var subChild in child.GetChildren()) { if (!subChild.IsExpandable) { varValue += $"<span class='childName'>{subChild.Name}</span> : {subChild.HtmlEncodedValueString}, "; } } varValue = varValue.TrimEnd(' ', ','); varValue += "}</span></span>"; } } } //var varValue = variable + " - "+ variable.GetType(); return(varValue); } catch (Exception ex) { return(ex.Message); } } return($"<div class='undefinedVariableType'>Session not found</div>" + $"<div class='variableLine'>A script needs to be executed in the session<br/>before the variable value can be inspected.</div>"); }