public IEnumerable <Variable> GetVariables(EVariableNamespace scope, params string[] names) { var command = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); command.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.GetVariable); var data = command.GetValue_Object()["data"] = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); data.GetValue_Object()["name"] = new asapJson.JsonNode(names.Select(name => new asapJson.JsonNode(name))); data.GetValue_Object()["scope"] = new asapJson.JsonNode((int)scope); this.WriteMessage(command); var response = this.ReadMessage((node) => (int)(node.GetValue_Object()["command"].GetValue_Number()) == (int)ERecvCommands.VariablesList); var variables = response.GetValue_Object()["data"]; if (variables.GetValueType() == JsonNode.EJType.Array) //Might be null if no variables found { foreach (var variable in variables.GetValue_Array()) { var name = variable.GetValue_Object()["name"].GetValue_String(); var type = variable.GetValue_Object()["type"].GetValue_String(); var value = ""; switch (type) { case "void": yield return(new Variable() { Name = name, Value = value, VariableType = Variable.ValueType.ANY }); break; case "array": { value = VariableArrayToString(variable.GetValue_Object()["value"]); var ns = (EVariableNamespace)variable.GetValue_Object()["ns"].GetValue_Number(); //Namespace the variable comes from yield return(new Variable() { Name = name, Value = value, VariableType = Variable.ValueType.ARRAY, Namespace = ns }); } break; default: { value = variable.GetValue_Object()["value"].GetValue_String(); var ns = (EVariableNamespace)variable.GetValue_Object()["ns"].GetValue_Number(); //Namespace the variable comes from yield return(new Variable() { Name = name, Value = value, VariableType = Variable.ValueType.Parse(type), Namespace = ns }); } break; } } } }
public void UpdateBreakpoint(Breakpoint b) { { var command = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); command.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.AddBreakpoint); command.GetValue_Object()["data"] = b.Serialize(); this.WriteMessage(command); } }
public bool Perform(EOperation op) { switch (op) { case EOperation.Continue: { var node = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); node.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.ContinueExecution); node.GetValue_Object()["data"] = new asapJson.JsonNode((int)EStepType.Continue); this.WriteMessage(node); return(true); } case EOperation.StepInto: { var node = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); node.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.ContinueExecution); node.GetValue_Object()["data"] = new asapJson.JsonNode((int)EStepType.StepInto); this.WriteMessage(node); return(true); } case EOperation.StepOver: { var node = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); node.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.ContinueExecution); node.GetValue_Object()["data"] = new asapJson.JsonNode((int)EStepType.StepOver); this.WriteMessage(node); return(true); } case EOperation.StepOut: { var node = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); node.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.ContinueExecution); node.GetValue_Object()["data"] = new asapJson.JsonNode((int)EStepType.StepOut); this.WriteMessage(node); return(true); } default: this.LastError = "Not Implemented"; return(false); } }
public bool Attach() { if (this.Pipe != null && this.Pipe.IsConnected) { throw new InvalidOperationException(); } if (this.Pipe != null) { this.Pipe.Dispose(); } this.Pipe = new NamedPipeClientStream(".", @"ArmaDebugEnginePipeIface", PipeDirection.InOut, PipeOptions.Asynchronous, System.Security.Principal.TokenImpersonationLevel.None, System.IO.HandleInheritability.None); this.Breakpoints = new List <Breakpoint>(); try { this.Pipe.Connect(1000); this.Pipe.ReadMode = PipeTransmissionMode.Message; this.PipeReadThread = new Thread(Thread_ReadPipeMessage); this.PipeReadThread.Start(); } catch (TimeoutException ex) { this.LastError = ex.Message; this.Pipe = null; return(false); } var command = new asapJson.JsonNode(new Dictionary <string, asapJson.JsonNode>()); command.GetValue_Object()["command"] = new asapJson.JsonNode((int)ESendCommands.GetVersionInfo); this.WriteMessage(command); var response = this.ReadMessage((node) => (int)(node.GetValue_Object()["command"].GetValue_Number()) == (int)ERecvCommands.VersionInfo); if (response.GetValue_Object()["gameType"].GetValueType() == JsonNode.EJType.String) //Might be null if init failed or attached too soon { var gameType = response.GetValue_Object()["gameType"].GetValue_String(); } if (response.GetValue_Object()["gameVersion"].GetValueType() == JsonNode.EJType.String) //Might be null if init failed or attached too soon { var gameVersion = response.GetValue_Object()["gameVersion"].GetValue_String(); } var arch = response.GetValue_Object()["arch"].GetValue_String(); var build = response.GetValue_Object()["build"].GetValue_Number(); var version = response.GetValue_Object()["version"].GetValue_String(); if (build < MinimalDebuggerBuild) { this.LastError = "Unsupported Debugger build: " + build + " \nMinimal build required: " + MinimalDebuggerBuild; Detach(); return(false); } return(true); }
private void Thread_ReadPipeMessage() { try { var buffer = new byte[2048]; while (this.Pipe.IsConnected) { var builder = new StringBuilder(); do { var ammount = this.Pipe.Read(buffer, 0, buffer.Length); for (int i = 0; i < ammount; i++) { builder.Append((char)buffer[i]); } } while (!this.Pipe.IsMessageComplete); if (builder.Length > 0) { var node = new asapJson.JsonNode(builder.ToString(), true); Logger.Log(NLog.LogLevel.Info, string.Format("RECV {0}", node.ToString())); if (node.GetValue_Object().ContainsKey("exception")) { this.OnError?.Invoke(this, new OnErrorEventArgs() { Message = node.GetValue_Object()["exception"].GetValue_String() }); } else { switch ((ERecvCommands)node.GetValue_Object()["command"].GetValue_Number()) { case ERecvCommands.HaltBreakpoint: case ERecvCommands.HaltStep: { var callstack = this.LastCallstack = node.GetValue_Object()["callstack"]; var instruction = node.GetValue_Object()["instruction"]; var fileOffsetNode = instruction.GetValue_Object()["fileOffset"]; var line = (int)fileOffsetNode.GetValue_Array()[0].GetValue_Number(); var col = (int)fileOffsetNode.GetValue_Array()[2].GetValue_Number(); this.OnHalt?.Invoke(this, new OnHaltEventArgs() { DocumentPath = instruction.GetValue_Object()["filename"].GetValue_String(), Col = col, Line = line }); } break; case ERecvCommands.HaltError: { var callstack = this.LastCallstack = node.GetValue_Object()["callstack"]; var error = node.GetValue_Object()["error"]; var fileOffsetNode = error.GetValue_Object()["fileOffset"]; var errorMessage = error.GetValue_Object()["message"]; //ToDo: display to user var fileContent = error.GetValue_Object()["content"]; //File content in case we don't have that file var line = (int)fileOffsetNode.GetValue_Array()[0].GetValue_Number(); var col = (int)fileOffsetNode.GetValue_Array()[2].GetValue_Number(); this.OnHalt?.Invoke(this, new OnHaltEventArgs() { DocumentPath = error.GetValue_Object()["filename"].GetValue_String(), Col = col, Line = line }); } break; case ERecvCommands.HaltScriptAssert: case ERecvCommands.HaltScriptHalt: { var callstack = this.LastCallstack = node.GetValue_Object()["callstack"]; var error = node.GetValue_Object()["halt"]; var fileOffsetNode = error.GetValue_Object()["fileOffset"]; var fileContent = error.GetValue_Object()["content"]; //File content in case we don't have that file var line = (int)fileOffsetNode.GetValue_Array()[0].GetValue_Number(); var col = (int)fileOffsetNode.GetValue_Array()[2].GetValue_Number(); this.OnHalt?.Invoke(this, new OnHaltEventArgs() { DocumentPath = error.GetValue_Object()["filename"].GetValue_String(), Col = col, Line = line }); } break; case ERecvCommands.ContinueExecution: { this.OnContinue?.Invoke(this, new OnContinueEventArgs() { }); } break; default: this.Messages.Add(node); break; } } } Thread.Sleep(10); } } catch (ObjectDisposedException) { } }